github.com/Axway/agent-sdk@v1.1.101/pkg/apic/provisioning/idp/provisioner.go (about) 1 package idp 2 3 import ( 4 "context" 5 6 management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1" 7 "github.com/Axway/agent-sdk/pkg/apic/provisioning" 8 "github.com/Axway/agent-sdk/pkg/authz/oauth" 9 "github.com/Axway/agent-sdk/pkg/config" 10 "github.com/Axway/agent-sdk/pkg/util" 11 ) 12 13 const ( 14 IDPTokenURL = "idpTokenURL" 15 ) 16 17 type Provisioner interface { 18 IsIDPCredential() bool 19 GetIDPProvider() oauth.Provider 20 GetIDPCredentialData() provisioning.IDPCredentialData 21 RegisterClient() error 22 UnregisterClient() error 23 GetAgentDetails() (map[string]string, error) 24 Validate() error 25 } 26 27 type provisioner struct { 28 app *management.ManagedApplication 29 credential *management.Credential 30 idpProvider oauth.Provider 31 credentialData *credData 32 agentDetail map[string]string 33 } 34 35 type ProvisionerOption func(p *provisioner) 36 37 func NewProvisioner(ctx context.Context, idpRegistry oauth.IdPRegistry, app *management.ManagedApplication, credential *management.Credential, opts ...oauth.ConfigOption) (Provisioner, error) { 38 p := &provisioner{ 39 app: app, 40 credential: credential, 41 credentialData: &credData{}, 42 agentDetail: make(map[string]string), 43 } 44 idpTokenURL, ok := p.credential.Spec.Data[IDPTokenURL].(string) 45 if ok && idpRegistry != nil { 46 idpProvider, err := idpRegistry.GetProviderByTokenEndpoint(ctx, idpTokenURL, opts...) 47 if err != nil { 48 return nil, err 49 } 50 51 if idpProvider != nil { 52 p.idpProvider = idpProvider 53 p.initCredentialData() 54 } 55 } 56 57 return p, nil 58 } 59 60 func getProvisionedData(cred *management.Credential) map[string]interface{} { 61 var provData map[string]interface{} 62 if cred.Data != nil { 63 if m, ok := cred.Data.(map[string]interface{}); ok { 64 provData = m 65 } 66 } 67 return provData 68 } 69 70 func (p *provisioner) initCredentialData() { 71 provData := getProvisionedData(p.credential) 72 if provData != nil { 73 p.credentialData.clientID = util.GetStringFromMapInterface(provisioning.OauthClientID, provData) 74 } 75 credData := p.credential.Spec.Data 76 77 p.credentialData.scopes = util.GetStringArrayFromMapInterface(provisioning.OauthScopes, credData) 78 p.credentialData.grantTypes = []string{util.GetStringFromMapInterface(provisioning.OauthGrantType, credData)} 79 p.credentialData.redirectURLs = util.GetStringArrayFromMapInterface(provisioning.OauthRedirectURIs, credData) 80 p.credentialData.tokenAuthMethod = util.GetStringFromMapInterface(provisioning.OauthTokenAuthMethod, credData) 81 p.credentialData.publicKey = util.GetStringFromMapInterface(provisioning.OauthJwks, credData) 82 p.credentialData.jwksURI = util.GetStringFromMapInterface(provisioning.OauthJwksURI, credData) 83 p.credentialData.certificate = util.GetStringFromMapInterface(provisioning.OauthCertificate, credData) 84 p.credentialData.certificateMetadata = util.GetStringFromMapInterface(provisioning.OauthCertificateMetadata, credData) 85 p.credentialData.tlsClientAuthSanDNS = util.GetStringFromMapInterface(provisioning.OauthTLSAuthSANDNS, credData) 86 p.credentialData.tlsClientAuthSanEmail = util.GetStringFromMapInterface(provisioning.OauthTLSAuthSANEmail, credData) 87 p.credentialData.tlsClientAuthSanIP = util.GetStringFromMapInterface(provisioning.OauthTLSAuthSANIP, credData) 88 p.credentialData.tlsClientAuthSanURI = util.GetStringFromMapInterface(provisioning.OauthTLSAuthSANURI, credData) 89 registrationToken := p.getRegistrationTokenFromAgentDetails() 90 if registrationToken != "" { 91 p.decryptRegistrationToken(registrationToken) 92 } 93 } 94 95 func (p *provisioner) IsIDPCredential() bool { 96 return p.idpProvider != nil 97 } 98 99 func (p *provisioner) GetIDPProvider() oauth.Provider { 100 return p.idpProvider 101 } 102 103 func (p *provisioner) GetIDPCredentialData() provisioning.IDPCredentialData { 104 return p.credentialData 105 } 106 107 func (p *provisioner) RegisterClient() error { 108 if !p.IsIDPCredential() { 109 return nil 110 } 111 112 // prepare external client metadata from CRD data 113 builder := oauth.NewClientMetadataBuilder(). 114 SetClientName(p.credential.GetName()). 115 SetScopes(p.credentialData.GetScopes()). 116 SetGrantTypes(p.credentialData.GetGrantTypes()). 117 SetTokenEndpointAuthMethod(p.credentialData.GetTokenEndpointAuthMethod()). 118 SetResponseType(p.credentialData.GetResponseTypes()). 119 SetRedirectURIs(p.credentialData.GetRedirectURIs()) 120 121 if p.credentialData.GetTokenEndpointAuthMethod() == config.PrivateKeyJWT { 122 builder.SetJWKS([]byte(formattedJWKS(p.credentialData.GetPublicKey()))). 123 SetJWKSURI(p.credentialData.GetJwksURI()) 124 } 125 126 if p.credentialData.GetTokenEndpointAuthMethod() == config.TLSClientAuth || p.credentialData.GetTokenEndpointAuthMethod() == config.SelfSignedTLSClientAuth { 127 builder.SetJWKS([]byte(formattedJWKS(p.credentialData.GetCertificate()))). 128 SetCertificateMetadata(p.credentialData.GetCertificateMetadata()). 129 SetTLSClientAuthSanDNS(p.credentialData.GetTLSClientAuthSanDNS()). 130 SetTLSClientAuthSanEmail(p.credentialData.GetTLSClientAuthSanEmail()). 131 SetTLSClientAuthSanIP(p.credentialData.GetTLSClientAuthSanIP()). 132 SetTLSClientAuthSanURI(p.credentialData.GetTLSClientAuthSanURI()) 133 } 134 135 clientMetadata, err := builder.Build() 136 if err != nil { 137 return err 138 } 139 140 // provision external client 141 resClientMetadata, err := p.idpProvider.RegisterClient(clientMetadata) 142 if err != nil { 143 return err 144 } 145 146 p.credentialData.registrationAccessToken = resClientMetadata.GetRegistrationAccessToken() 147 p.credentialData.clientID = resClientMetadata.GetClientID() 148 p.credentialData.clientSecret = resClientMetadata.GetClientSecret() 149 150 return nil 151 } 152 153 func (p *provisioner) UnregisterClient() error { 154 if !p.IsIDPCredential() { 155 return nil 156 } 157 158 err := p.idpProvider.UnregisterClient(p.credentialData.GetClientID(), p.credentialData.registrationAccessToken) 159 if err != nil { 160 return err 161 } 162 163 p.credentialData.clientID = p.credentialData.GetClientID() 164 return nil 165 } 166 167 func (p *provisioner) GetAgentDetails() (map[string]string, error) { 168 registrationToken, err := p.encryptRegistrationToken() 169 if err != nil { 170 return nil, err 171 } 172 return p.createAgentDetails(registrationToken), nil 173 } 174 175 func (p *provisioner) Validate() error { 176 if !p.IsIDPCredential() { 177 return nil 178 } 179 180 return p.idpProvider.Validate() 181 } 182 183 func (p *provisioner) encryptRegistrationToken() (string, error) { 184 if p.credentialData.registrationAccessToken != "" { 185 enc, err := util.NewGCMEncryptor([]byte(p.app.Spec.Security.EncryptionKey)) 186 if err != nil { 187 return "", err 188 } 189 190 ert, err := enc.Encrypt(p.credentialData.registrationAccessToken) 191 if err != nil { 192 return "", err 193 } 194 return ert, nil 195 } 196 return "", nil 197 } 198 199 func (p *provisioner) decryptRegistrationToken(encryptedToken string) error { 200 if encryptedToken != "" { 201 dc, err := util.NewGCMDecryptor([]byte(p.app.Spec.Security.EncryptionKey)) 202 if err != nil { 203 return err 204 } 205 206 decrypted, err := dc.Decrypt(encryptedToken) 207 if err != nil { 208 return err 209 } 210 p.credentialData.registrationAccessToken = decrypted 211 } 212 return nil 213 } 214 215 func (p *provisioner) createAgentDetails(registrationToken string) map[string]string { 216 agentDetail := make(map[string]string) 217 if registrationToken != "" { 218 agentDetail[provisioning.OauthRegistrationToken] = registrationToken 219 } 220 return agentDetail 221 } 222 223 func (p *provisioner) getRegistrationTokenFromAgentDetails() string { 224 registrationToken, _ := util.GetAgentDetailsValue(p.credential, provisioning.OauthRegistrationToken) 225 return registrationToken 226 }