Skip to content

Commit

Permalink
APIGOV-24312 - IDP auth config validation
Browse files Browse the repository at this point in the history
  • Loading branch information
vivekschauhan committed Aug 9, 2023
1 parent 12f823a commit 987472e
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 99 deletions.
137 changes: 80 additions & 57 deletions pkg/authz/oauth/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,63 +84,7 @@ func NewProvider(idp corecfg.IDPConfig, tlsCfg corecfg.TLSConfig, proxyURL strin
p.authServerMetadata = metadata

if p.cfg.GetAuthConfig() != nil {
tokenEndpoint := p.authServerMetadata.TokenEndpoint
switch p.cfg.GetAuthConfig().GetType() {
case IDPAuthTypeClient:
fallthrough
case IDPAuthTypeClientSecretPost:
p.authClient, err = NewAuthClient(tokenEndpoint, apiClient,
WithServerName(idp.GetIDPName()),
WithClientSecretPostAuth(p.cfg.GetAuthConfig().GetClientID(), p.cfg.GetAuthConfig().GetClientSecret(), p.cfg.GetAuthConfig().GetClientScope()))
case IDPAuthTypeClientSecretBasic:
p.authClient, err = NewAuthClient(tokenEndpoint, apiClient,
WithServerName(idp.GetIDPName()),
WithClientSecretBasicAuth(p.cfg.GetAuthConfig().GetClientID(), p.cfg.GetAuthConfig().GetClientSecret(), p.cfg.GetAuthConfig().GetClientScope()))
case IDPAuthTypeClientSecretJWT:
p.authClient, err = NewAuthClient(tokenEndpoint, apiClient,
WithServerName(idp.GetIDPName()),
WithClientSecretJwtAuth(
p.cfg.GetAuthConfig().GetClientID(),
p.cfg.GetAuthConfig().GetClientSecret(),
p.cfg.GetAuthConfig().GetClientScope(),
p.cfg.GetAuthConfig().GetClientID(),
metadata.Issuer,
))
case IDPAuthTypePrivateKeyJWT:
keyReader := NewKeyReader(
p.cfg.GetAuthConfig().GetPrivateKey(),
p.cfg.GetAuthConfig().GetPublicKey(),
p.cfg.GetAuthConfig().GetKeyPassword(),
)
privateKey, keyErr := keyReader.GetPrivateKey()
if keyErr != nil {
return nil, keyErr
}

publicKey, keyErr := keyReader.GetPublicKey()
if keyErr != nil {
return nil, keyErr
}
p.authClient, err = NewAuthClient(tokenEndpoint, apiClient,
WithServerName(idp.GetIDPName()),
WithKeyPairAuth(
p.cfg.GetAuthConfig().GetClientID(),
p.cfg.GetAuthConfig().GetClientID(),
metadata.Issuer,
privateKey,
publicKey,
p.cfg.GetAuthConfig().GetClientScope(),
),
)
case IDPAuthTypeTLSClientAuth:
fallthrough
case IDPAuthTypeSelfSignedTLSClientAuth:
p.authClient, err = NewAuthClient(tokenEndpoint, apiClient,
WithServerName(idp.GetIDPName()),
WithTLSClientAuth(p.cfg.GetAuthConfig().GetClientID(), p.cfg.GetAuthConfig().GetClientScope()))
default:
err = fmt.Errorf("%s", "unknown IdP auth type")
}
p.authClient, err = p.createAuthClient()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -168,6 +112,85 @@ func (p *provider) fetchMetadata() (*AuthorizationServerMetadata, error) {

}

func (p *provider) createAuthClient() (AuthClient, error) {
switch p.cfg.GetAuthConfig().GetType() {
case IDPAuthTypeClient:
fallthrough
case IDPAuthTypeClientSecretPost:
return p.createClientSecretPostAuthClient()
case IDPAuthTypeClientSecretBasic:
return p.createClientSecretBasicAuthClient()
case IDPAuthTypeClientSecretJWT:
return p.createClientSecretJWTAuthClient()
case IDPAuthTypePrivateKeyJWT:
return p.createPrivateKeyJWTAuthClient()
case IDPAuthTypeTLSClientAuth:
fallthrough
case IDPAuthTypeSelfSignedTLSClientAuth:
return p.createTLSAuthClient()
default:
return nil, fmt.Errorf("%s", "unknown IdP auth type")
}
}

func (p *provider) createClientSecretPostAuthClient() (AuthClient, error) {
return NewAuthClient(p.GetTokenEndpoint(), p.apiClient,
WithServerName(p.cfg.GetIDPName()),
WithClientSecretPostAuth(p.cfg.GetAuthConfig().GetClientID(), p.cfg.GetAuthConfig().GetClientSecret(), p.cfg.GetAuthConfig().GetClientScope()))
}

func (p *provider) createClientSecretBasicAuthClient() (AuthClient, error) {
return NewAuthClient(p.GetTokenEndpoint(), p.apiClient,
WithServerName(p.cfg.GetIDPName()),
WithClientSecretBasicAuth(p.cfg.GetAuthConfig().GetClientID(), p.cfg.GetAuthConfig().GetClientSecret(), p.cfg.GetAuthConfig().GetClientScope()))
}

func (p *provider) createClientSecretJWTAuthClient() (AuthClient, error) {
return NewAuthClient(p.GetTokenEndpoint(), p.apiClient,
WithServerName(p.cfg.GetIDPName()),
WithClientSecretJwtAuth(
p.cfg.GetAuthConfig().GetClientID(),
p.cfg.GetAuthConfig().GetClientSecret(),
p.cfg.GetAuthConfig().GetClientScope(),
p.cfg.GetAuthConfig().GetClientID(),
p.authServerMetadata.Issuer,
))
}

func (p *provider) createPrivateKeyJWTAuthClient() (AuthClient, error) {
keyReader := NewKeyReader(
p.cfg.GetAuthConfig().GetPrivateKey(),
p.cfg.GetAuthConfig().GetPublicKey(),
p.cfg.GetAuthConfig().GetKeyPassword(),
)
privateKey, keyErr := keyReader.GetPrivateKey()
if keyErr != nil {
return nil, keyErr
}

publicKey, keyErr := keyReader.GetPublicKey()
if keyErr != nil {
return nil, keyErr
}
return NewAuthClient(p.GetTokenEndpoint(), p.apiClient,
WithServerName(p.cfg.GetIDPName()),
WithKeyPairAuth(
p.cfg.GetAuthConfig().GetClientID(),
p.cfg.GetAuthConfig().GetClientID(),
p.authServerMetadata.Issuer,
privateKey,
publicKey,
p.cfg.GetAuthConfig().GetClientScope(),
),
)
}

func (p *provider) createTLSAuthClient() (AuthClient, error) {
return NewAuthClient(p.GetTokenEndpoint(), p.apiClient,
WithServerName(p.cfg.GetIDPName()),
WithTLSClientAuth(p.cfg.GetAuthConfig().GetClientID(), p.cfg.GetAuthConfig().GetClientScope()))
}

// GetName - returns the name of the provider
func (p *provider) GetName() string {
return p.cfg.GetIDPName()
Expand Down
40 changes: 15 additions & 25 deletions pkg/config/authconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,40 +82,30 @@ func (a *AuthConfiguration) validate() {
a.validatePublicKey()
}

func (a *AuthConfiguration) validatePrivateKey() {
if a.GetPrivateKey() == "" {
exception.Throw(ErrBadConfig.FormatError(pathAuthPrivateKey))
func validateAuthFileConfig(configKeyName, authFile, dataEnvVar, errMsg string) {
if authFile == "" {
exception.Throw(ErrBadConfig.FormatError(configKeyName))
} else {
if !fileExists(a.GetPrivateKey()) {
privateKeyData := os.Getenv("CENTRAL_AUTH_PRIVATEKEY_DATA")
if privateKeyData == "" {
exception.Throw(ErrBadConfig.FormatError(pathAuthPrivateKey))
if !fileExists(authFile) && dataEnvVar != "" {
data := os.Getenv(dataEnvVar)
if data == "" {
exception.Throw(ErrBadConfig.FormatError(configKeyName))
}
saveKeyData(a.GetPrivateKey(), privateKeyData)
saveKeyData(authFile, data)
}
// Validate that the file is readable
if _, err := os.Open(a.GetPrivateKey()); err != nil {
exception.Throw(ErrReadingKeyFile.FormatError("private key", a.GetPrivateKey()))
if _, err := os.Open(authFile); err != nil {
exception.Throw(ErrReadingKeyFile.FormatError(errMsg, authFile))
}
}
}

func (a *AuthConfiguration) validatePrivateKey() {
validateAuthFileConfig(pathAuthPrivateKey, a.GetPrivateKey(), "CENTRAL_AUTH_PRIVATEKEY_DATA", "private key")
}

func (a *AuthConfiguration) validatePublicKey() {
if a.GetPublicKey() == "" {
exception.Throw(ErrBadConfig.FormatError(pathAuthPublicKey))
} else {
if !fileExists(a.GetPublicKey()) {
publicKeyData := os.Getenv("CENTRAL_AUTH_PUBLICKEY_DATA")
if publicKeyData == "" {
exception.Throw(ErrBadConfig.FormatError(pathAuthPublicKey))
}
saveKeyData(a.GetPublicKey(), publicKeyData)
}
// Validate that the file is readable
if _, err := os.Open(a.GetPublicKey()); err != nil {
exception.Throw(ErrReadingKeyFile.FormatError("public key", a.GetPublicKey()))
}
}
validateAuthFileConfig(pathAuthPublicKey, a.GetPublicKey(), "CENTRAL_AUTH_PUBLICKEY_DATA", "public key")
}

// GetTokenURL - Returns the token URL
Expand Down
74 changes: 57 additions & 17 deletions pkg/config/externalidpconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ type IDPAuthConfig interface {
// GetClientScope - Scopes used for requesting the token using the ID client
GetClientScope() string
// validate - Validates the IDP auth configuration
validate(isMTLS bool)
validate(tlsCfg TLSConfig)
// GetPrivateKey() - private key to be used for private_key_jwt authentication
GetPrivateKey() string
// GetPublicKey() - public key to be used for private_key_jwt authentication
Expand Down Expand Up @@ -271,11 +271,7 @@ func (i *IDPConfiguration) validate() {
exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldMetadataURL))
}

isMTLS := false
if i.TLSConfig != nil {
isMTLS = i.TLSConfig.(*TLSConfiguration).ClientCertificatePath != "" && i.TLSConfig.(*TLSConfiguration).ClientKeyPath != ""
}
i.AuthConfig.validate(isMTLS)
i.AuthConfig.validate(i.TLSConfig)
}

// GetType - type of authentication mechanism to use "accessToken" or "client"
Expand Down Expand Up @@ -319,25 +315,69 @@ func (i *IDPAuthConfiguration) GetKeyPassword() string {
}

// validate - Validates the IDP auth configuration
func (i *IDPAuthConfiguration) validate(isMTLS bool) {
func (i *IDPAuthConfiguration) validate(tlsCfg TLSConfig) {
if ok := validIDPAuthType[i.GetType()]; !ok {
exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthType))
}

if i.GetType() == accessToken && i.GetAccessToken() == "" {
switch i.GetType() {
case accessToken:
i.validateAccessTokenAuthConfig()
case client:
fallthrough
case clientSecretBasic:
fallthrough
case clientSecretPost:
fallthrough
case clientSecretJwt:
i.validateClientSecretAuthConfig()
case privateKeyJwt:
i.validatePrivateKeyJwtAuthConfig()
case tlsClientAuth:
fallthrough
case selfSignedTlsClientAuth:
i.validateTLSClientAuthConfig(tlsCfg)
}
}

func (i *IDPAuthConfiguration) validateAccessTokenAuthConfig() {
if i.GetAccessToken() == "" {
exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthAccessToken))
}
}

func (i *IDPAuthConfiguration) validateClientIDConfig() {
if i.GetClientID() == "" {
exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthClientID))
}
}

if i.GetType() == client {
if i.GetClientID() == "" {
exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthClientID))
}
if !isMTLS {
if i.GetClientSecret() == "" {
exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthClientSecret))
}
}
func (i *IDPAuthConfiguration) validateClientSecretConfig() {
if i.GetClientSecret() == "" {
exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthClientSecret))
}
}

func (i *IDPAuthConfiguration) validateClientSecretAuthConfig() {
i.validateClientIDConfig()
i.validateClientSecretConfig()
}

func (i *IDPAuthConfiguration) validatePrivateKeyJwtAuthConfig() {
i.validateClientIDConfig()

validateAuthFileConfig(pathExternalIDP+"."+fldAuthPrivateKey, i.PrivateKey, "", "private key")
validateAuthFileConfig(pathExternalIDP+"."+fldAuthPublicKey, i.PublicKey, "", "public key")
}

func (i *IDPAuthConfiguration) validateTLSClientAuthConfig(tlsCfg TLSConfig) {
i.validateClientIDConfig()

if tlsCfg == nil {
exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldSSLClientCertPath))
}
validateAuthFileConfig(pathExternalIDP+"."+fldSSLClientCertPath, tlsCfg.(*TLSConfiguration).ClientCertificatePath, "", "tls client certificate")
validateAuthFileConfig(pathExternalIDP+"."+fldSSLClientKeyPath, tlsCfg.(*TLSConfiguration).ClientKeyPath, "", "tls client key")
}

func addExternalIDPProperties(props properties.Properties) {
Expand Down

0 comments on commit 987472e

Please sign in to comment.