yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/saml_provider.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aws 16 17 import ( 18 "fmt" 19 "strings" 20 "time" 21 "unicode" 22 23 "yunion.io/x/jsonutils" 24 "yunion.io/x/pkg/errors" 25 26 "yunion.io/x/cloudmux/pkg/apis/cloudid" 27 api "yunion.io/x/cloudmux/pkg/apis/cloudid" 28 compute_api "yunion.io/x/cloudmux/pkg/apis/compute" 29 "yunion.io/x/onecloud/pkg/cloudid/options" 30 "yunion.io/x/cloudmux/pkg/cloudprovider" 31 "yunion.io/x/cloudmux/pkg/multicloud" 32 "yunion.io/x/onecloud/pkg/util/httputils" 33 "yunion.io/x/onecloud/pkg/util/samlutils" 34 ) 35 36 type SAMLProvider struct { 37 multicloud.SResourceBase 38 AwsTags 39 client *SAwsClient 40 41 SAMLMetadataDocument string `xml:"SAMLMetadataDocument"` 42 Arn string `xml:"Arn"` 43 ValidUntil time.Time `xml:"ValidUntil"` 44 CreateDate time.Time `xml:"CreateDate"` 45 } 46 47 func (self *SAMLProvider) GetGlobalId() string { 48 return self.Arn 49 } 50 51 func (self *SAMLProvider) GetId() string { 52 return self.Arn 53 } 54 55 func (self *SAMLProvider) GetName() string { 56 if info := strings.Split(self.Arn, "/"); len(info) > 0 { 57 return info[len(info)-1] 58 } 59 return self.Arn 60 } 61 62 func (self *SAMLProvider) GetStatus() string { 63 return api.SAML_PROVIDER_STATUS_AVAILABLE 64 } 65 66 func (self *SAMLProvider) Delete() error { 67 return self.client.DeleteSAMLProvider(self.Arn) 68 } 69 70 func (self *SAMLProvider) GetAuthUrl() string { 71 input := samlutils.SIdpInitiatedLoginInput{ 72 EntityID: cloudprovider.SAML_ENTITY_ID_AWS_CN, 73 IdpId: self.client.cpcfg.AccountId, 74 } 75 if self.client.GetAccessEnv() == compute_api.CLOUD_ACCESS_ENV_AWS_GLOBAL { 76 input.EntityID = cloudprovider.SAML_ENTITY_ID_AWS 77 } 78 return httputils.JoinPath(options.Options.ApiServer, cloudid.SAML_IDP_PREFIX, fmt.Sprintf("sso?%s", jsonutils.Marshal(input).QueryString())) 79 } 80 81 func (self *SAMLProvider) GetMetadataDocument() (*samlutils.EntityDescriptor, error) { 82 saml, err := self.client.GetSAMLProvider(self.Arn) 83 if err != nil { 84 return nil, errors.Wrapf(err, "GetSAMLProvider(%s)", self.Arn) 85 } 86 metadata, err := samlutils.ParseMetadata([]byte(saml.SAMLMetadataDocument)) 87 if err != nil { 88 return nil, errors.Wrapf(err, "ParseMetadata") 89 } 90 return &metadata, nil 91 } 92 93 func (self *SAMLProvider) UpdateMetadata(metadata samlutils.EntityDescriptor) error { 94 _, err := self.client.UpdateSAMLProvider(self.Arn, metadata.String()) 95 return err 96 } 97 98 type SAMLProviders struct { 99 SAMLProviderList []SAMLProvider `xml:"SAMLProviderList>member"` 100 } 101 102 func (self *SAwsClient) ListSAMLProviders() ([]SAMLProvider, error) { 103 result := SAMLProviders{} 104 err := self.iamRequest("ListSAMLProviders", nil, &result) 105 if err != nil { 106 return nil, errors.Wrapf(err, "ListSAMLProviders") 107 } 108 return result.SAMLProviderList, nil 109 } 110 111 func (self *SAwsClient) GetSAMLProvider(arn string) (*SAMLProvider, error) { 112 result := &SAMLProvider{client: self, Arn: arn} 113 params := map[string]string{"SAMLProviderArn": arn} 114 err := self.iamRequest("GetSAMLProvider", params, result) 115 if err != nil { 116 return nil, errors.Wrapf(err, "GetSAMLProvider") 117 } 118 return result, nil 119 } 120 121 func (self *SAwsClient) DeleteSAMLProvider(arn string) error { 122 params := map[string]string{"SAMLProviderArn": arn} 123 return self.iamRequest("DeleteSAMLProvider", params, nil) 124 } 125 126 func (self *SAwsClient) CreateSAMLProvider(name, metadata string) (*SAMLProvider, error) { 127 name = func() string { 128 ret := "" 129 for _, s := range name { 130 if unicode.IsLetter(s) || unicode.IsNumber(s) || s == '.' || s == '_' || s == '-' { 131 ret += string(s) 132 } else { 133 ret += "-" 134 } 135 } 136 if len(ret) > 128 { 137 ret = ret[:128] 138 } 139 return ret 140 }() 141 params := map[string]string{ 142 "Name": name, 143 "SAMLMetadataDocument": metadata, 144 } 145 result := struct { 146 SAMLProviderArn string `xml:"SAMLProviderArn"` 147 }{} 148 err := self.iamRequest("CreateSAMLProvider", params, &result) 149 if err != nil { 150 return nil, errors.Wrapf(err, "CreateSAMLProvider") 151 } 152 return self.GetSAMLProvider(result.SAMLProviderArn) 153 } 154 155 func (self *SAwsClient) UpdateSAMLProvider(arn, metadata string) (*SAMLProvider, error) { 156 params := map[string]string{ 157 "SAMLProviderArn": arn, 158 "SAMLMetadataDocument": metadata, 159 } 160 saml := &SAMLProvider{client: self} 161 err := self.iamRequest("UpdateSAMLProvider", params, saml) 162 if err != nil { 163 return nil, errors.Wrapf(err, "UpdateSAMLProvider") 164 } 165 return saml, nil 166 } 167 168 func (self *SAwsClient) GetICloudSAMLProviders() ([]cloudprovider.ICloudSAMLProvider, error) { 169 providers, err := self.ListSAMLProviders() 170 if err != nil { 171 return nil, errors.Wrapf(err, "ListSAMLProviders") 172 } 173 ret := []cloudprovider.ICloudSAMLProvider{} 174 for i := range providers { 175 providers[i].client = self 176 ret = append(ret, &providers[i]) 177 } 178 return ret, nil 179 }