Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AUTH-5315 adds new conditional_access_enabled attr to access IDP #1344

Merged
merged 3 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changelog/1344.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```release-note:enhancement
access_identity_provider: add attr conditional_access_enabled
```

```release-note:enhancement
access_group: add auth_context group ruletype
```

```release-note:enhancement
access_identity_provider: add auth context list/put endpoint
```
9 changes: 9 additions & 0 deletions access_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ type AccessGroupSAML struct {
} `json:"saml"`
}

// AccessGroupAzureAuthContext is used to configure access based on Azure auth contexts.
type AccessGroupAzureAuthContext struct {
AuthContext struct {
jacobbednarz marked this conversation as resolved.
Show resolved Hide resolved
ID string `json:"id"`
IdentityProviderID string `json:"identity_provider_id"`
ACID string `json:"ac_id"`
} `json:"auth_context"`
}

// AccessGroupAuthMethod is used for managing access by the "amr"
// (Authentication Methods References) identifier. For example, an
// application may want to require that users authenticate using a hardware
Expand Down
111 changes: 88 additions & 23 deletions access_identity_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,30 @@ type AccessIdentityProvider struct {
//
// API reference: https://developers.cloudflare.com/access/configuring-identity-providers/
type AccessIdentityProviderConfiguration struct {
APIToken string `json:"api_token,omitempty"`
AppsDomain string `json:"apps_domain,omitempty"`
Attributes []string `json:"attributes,omitempty"`
AuthURL string `json:"auth_url,omitempty"`
CentrifyAccount string `json:"centrify_account,omitempty"`
CentrifyAppID string `json:"centrify_app_id,omitempty"`
CertsURL string `json:"certs_url,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"client_secret,omitempty"`
Claims []string `json:"claims,omitempty"`
Scopes []string `json:"scopes,omitempty"`
DirectoryID string `json:"directory_id,omitempty"`
EmailAttributeName string `json:"email_attribute_name,omitempty"`
IdpPublicCert string `json:"idp_public_cert,omitempty"`
IssuerURL string `json:"issuer_url,omitempty"`
OktaAccount string `json:"okta_account,omitempty"`
OneloginAccount string `json:"onelogin_account,omitempty"`
RedirectURL string `json:"redirect_url,omitempty"`
SignRequest bool `json:"sign_request,omitempty"`
SsoTargetURL string `json:"sso_target_url,omitempty"`
SupportGroups bool `json:"support_groups,omitempty"`
TokenURL string `json:"token_url,omitempty"`
PKCEEnabled *bool `json:"pkce_enabled,omitempty"`
APIToken string `json:"api_token,omitempty"`
AppsDomain string `json:"apps_domain,omitempty"`
Attributes []string `json:"attributes,omitempty"`
AuthURL string `json:"auth_url,omitempty"`
CentrifyAccount string `json:"centrify_account,omitempty"`
CentrifyAppID string `json:"centrify_app_id,omitempty"`
CertsURL string `json:"certs_url,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"client_secret,omitempty"`
Claims []string `json:"claims,omitempty"`
Scopes []string `json:"scopes,omitempty"`
DirectoryID string `json:"directory_id,omitempty"`
EmailAttributeName string `json:"email_attribute_name,omitempty"`
IdpPublicCert string `json:"idp_public_cert,omitempty"`
IssuerURL string `json:"issuer_url,omitempty"`
OktaAccount string `json:"okta_account,omitempty"`
OneloginAccount string `json:"onelogin_account,omitempty"`
RedirectURL string `json:"redirect_url,omitempty"`
SignRequest bool `json:"sign_request,omitempty"`
SsoTargetURL string `json:"sso_target_url,omitempty"`
SupportGroups bool `json:"support_groups,omitempty"`
TokenURL string `json:"token_url,omitempty"`
PKCEEnabled *bool `json:"pkce_enabled,omitempty"`
ConditionalAccessEnabled bool `json:"conditional_access_enabled,omitempty"`
}

type AccessIdentityProviderScimConfiguration struct {
Expand Down Expand Up @@ -89,6 +90,22 @@ type UpdateAccessIdentityProviderParams struct {
ScimConfig AccessIdentityProviderScimConfiguration `json:"scim_config"`
}

// AccessAuthContext represents an Access Azure Identity Provider Auth Context.
type AccessAuthContext struct {
ID string `json:"id"`
UID string `json:"uid"`
ACID string `json:"ac_id"`
DisplayName string `json:"display_name"`
Description string `json:"description"`
}

// AccessAuthContextsListResponse represents the response from the list
// Access Auth Contexts endpoint.
type AccessAuthContextsListResponse struct {
Result []AccessAuthContext `json:"result"`
Response
}

// ListAccessIdentityProviders returns all Access Identity Providers for an
// account or zone.
//
Expand Down Expand Up @@ -235,3 +252,51 @@ func (api *API) DeleteAccessIdentityProvider(ctx context.Context, rc *ResourceCo

return accessIdentityProviderResponse.Result, nil
}

// ListAccessIdentityProviderAuthContexts returns an identity provider's auth contexts
// AzureAD only
// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-get-an-access-identity-provider
// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-get-an-access-identity-provider
func (api *API) ListAccessIdentityProviderAuthContexts(ctx context.Context, rc *ResourceContainer, identityProviderID string) ([]AccessAuthContext, error) {
uri := fmt.Sprintf("/%s/%s/access/identity_providers/%s/auth_context", rc.Level, rc.Identifier, identityProviderID)

res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return []AccessAuthContext{}, err
}

var accessAuthContextListResponse AccessAuthContextsListResponse
err = json.Unmarshal(res, &accessAuthContextListResponse)
if err != nil {
return []AccessAuthContext{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return accessAuthContextListResponse.Result, nil
}

// UpdateAccessIdentityProviderAuthContexts updates an existing Access Identity
// Provider.
// AzureAD only
// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-refresh-an-access-identity-provider-auth-contexts
// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-update-an-access-identity-provider
func (api *API) UpdateAccessIdentityProviderAuthContexts(ctx context.Context, rc *ResourceContainer, identityProviderID string) (AccessIdentityProvider, error) {
uri := fmt.Sprintf(
"/%s/%s/access/identity_providers/%s/auth_context",
rc.Level,
rc.Identifier,
identityProviderID,
)

res, err := api.makeRequestContext(ctx, http.MethodPut, uri, nil)
jacobbednarz marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return AccessIdentityProvider{}, err
}

var accessIdentityProviderResponse AccessIdentityProviderResponse
err = json.Unmarshal(res, &accessIdentityProviderResponse)
if err != nil {
return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return accessIdentityProviderResponse.Result, nil
}
131 changes: 126 additions & 5 deletions access_identity_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ func TestCreateAccessIdentityProvider(t *testing.T) {
"type": "github",
"config": {
"client_id": "example_id",
"client_secret": "a-secret-key"
"client_secret": "a-secret-key",
"conditional_access_enabled": true
}
}
}
Expand All @@ -151,8 +152,9 @@ func TestCreateAccessIdentityProvider(t *testing.T) {
Name: "Widget Corps OTP",
Type: "github",
Config: AccessIdentityProviderConfiguration{
ClientID: "example_id",
ClientSecret: "a-secret-key",
ClientID: "example_id",
ClientSecret: "a-secret-key",
ConditionalAccessEnabled: true,
},
}

Expand All @@ -161,8 +163,9 @@ func TestCreateAccessIdentityProvider(t *testing.T) {
Name: "Widget Corps OTP",
Type: "github",
Config: AccessIdentityProviderConfiguration{
ClientID: "example_id",
ClientSecret: "a-secret-key",
ClientID: "example_id",
ClientSecret: "a-secret-key",
ConditionalAccessEnabled: true,
},
}

Expand Down Expand Up @@ -293,3 +296,121 @@ func TestDeleteAccessIdentityProvider(t *testing.T) {
assert.Equal(t, want, actual)
}
}

func TestListAccessIdentityProviderAuthContexts(t *testing.T) {
setup()
defer teardown()

handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": [
{
"id": "04709095-568a-40c4-bf23-5d9edbefe21e",
"uid": "04709095-568a-40c4-bf23-5d9edbefe21e",
"ac_id": "c1",
"display_name": "test_c1",
"description": ""
},
{
"id": "a6c9b024-8fd1-48b7-9a05-8bca3a43f758",
"uid": "a6c9b024-8fd1-48b7-9a05-8bca3a43f758",
"ac_id": "c25",
"display_name": "test_c25",
"description": ""
}
]
}
`)
}

want := []AccessAuthContext{
{
ID: "04709095-568a-40c4-bf23-5d9edbefe21e",
UID: "04709095-568a-40c4-bf23-5d9edbefe21e",
ACID: "c1",
DisplayName: "test_c1",
Description: "",
},
{
ID: "a6c9b024-8fd1-48b7-9a05-8bca3a43f758",
UID: "a6c9b024-8fd1-48b7-9a05-8bca3a43f758",
ACID: "c25",
DisplayName: "test_c25",
Description: "",
},
}

mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/auth_context", handler)

actual, err := client.ListAccessIdentityProviderAuthContexts(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")

if assert.NoError(t, err) {
assert.Equal(t, want, actual)
}

mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/auth_context", handler)

actual, err = client.ListAccessIdentityProviderAuthContexts(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")

if assert.NoError(t, err) {
assert.Equal(t, want, actual)
}
}

func TestUpdateAccessIdentityProviderAuthContext(t *testing.T) {
setup()
defer teardown()

handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
"name": "Widget Corps",
"type": "AzureAD",
"config": {
"client_id": "example_id",
"client_secret": "a-secret-key",
"conditional_access_enabled": true
}
}
}
`)
}

want := AccessIdentityProvider{
ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
Name: "Widget Corps",
Type: "AzureAD",
Config: AccessIdentityProviderConfiguration{
ClientID: "example_id",
ClientSecret: "a-secret-key",
ConditionalAccessEnabled: true,
},
}

mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/auth_context", handler)

actual, err := client.UpdateAccessIdentityProviderAuthContexts(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")

if assert.NoError(t, err) {
assert.Equal(t, want, actual)
}

mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/auth_context", handler)

actual, err = client.UpdateAccessIdentityProviderAuthContexts(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415")

if assert.NoError(t, err) {
assert.Equal(t, want, actual)
}
}
Loading
Loading