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-4233 adds saas app fields and types #900

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 35 additions & 3 deletions access_application.go
Expand Up @@ -16,9 +16,14 @@ type AccessApplicationType string

// These constants represent all valid application types.
const (
SelfHosted AccessApplicationType = "self_hosted"
SSH AccessApplicationType = "ssh"
VNC AccessApplicationType = "vnc"
SelfHosted AccessApplicationType = "self_hosted"
SSH AccessApplicationType = "ssh"
VNC AccessApplicationType = "vnc"
Biso AccessApplicationType = "biso"
AppLauncher AccessApplicationType = "app_launcher"
Warp AccessApplicationType = "warp"
Bookmark AccessApplicationType = "bookmark"
Saas AccessApplicationType = "saas"
)

// AccessApplication represents an Access application.
Expand All @@ -39,6 +44,7 @@ type AccessApplication struct {
CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
SaasApplication *SaasApplication `json:"saas_app,omitempty"`
AutoRedirectToIdentity bool `json:"auto_redirect_to_identity,omitempty"`
SkipInterstitial bool `json:"skip_interstitial,omitempty"`
AppLauncherVisible bool `json:"app_launcher_visible,omitempty"`
Expand Down Expand Up @@ -81,6 +87,32 @@ type AccessApplicationDetailResponse struct {
Result AccessApplication `json:"result"`
}

type SourceConfig struct {
Name string `json:"name,omitempty"`
NameByIDP map[string]string `json:"name_by_idp,omitempty"`
}

type SAMLAttributeConfig struct {
Name string `json:"name,omitempty"`
NameFormat string `json:"name_format,omitempty"`
FriendlyName string `json:"friendly_name,omitempty"`
Required bool `json:"required,omitempty"`
Source SourceConfig `json:"source"`
}

type SaasApplication struct {
AppID string `json:"app_id,omitempty"`
ConsumerServiceUrl string `json:"consumer_service_url,omitempty"`
SPEntityID string `json:"sp_entity_id,omitempty"`
PublicKey string `json:"public_key,omitempty"`
IDPEntityID string `json:"idp_entity_id,omitempty"`
NameIDFormat string `json:"name_id_format,omitempty"`
SSOEndpoint string `json:"sso_endpoint,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
CustomAttributes []SAMLAttributeConfig `json:"custom_attributes,omitempty"`
}

// AccessApplications returns all applications within an account.
//
// API reference: https://api.cloudflare.com/#access-applications-list-access-applications
Expand Down
145 changes: 145 additions & 0 deletions access_application_test.go
Expand Up @@ -543,3 +543,148 @@ func TestCreatePrivateAccessApplication(t *testing.T) {
assert.Equal(t, fullAccessApplication, actual)
}
}

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

handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "480f4f69-1a28-4fdd-9240-1ed29f0ac1db",
"created_at": "2014-01-01T05:20:00.12345Z",
"updated_at": "2014-01-01T05:20:00.12345Z",
"aud": "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893",
"name": "Admin Saas App",
"domain": "example.cloudflareaccess.com/cdn-cgi/access/sso/saml/737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893",
"type": "saas",
"session_duration": "24h",
"allowed_idps": [],
"auto_redirect_to_identity": false,
"enable_binding_cookie": false,
"custom_deny_url": "https://www.example.com",
"custom_deny_message": "denied!",
"logo_url": "https://www.example.com/example.png",
"skip_interstitial": true,
"app_launcher_visible": true,
"service_auth_401_redirect": true,
"saas_app": {
"consumer_service_url": "https://saas.example.com",
"sp_entity_id": "dash.example.com",
"name_id_format": "id",
"custom_attributes": [
{
"name": "test1",
"name_format": "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified",
"source": {
"name": "test1"
}
},
{
"name": "test2",
"name_format": "urn:oasis:names:tc:SAML:2.0:attrname-format:basic",
"source": {
"name": "test2"
}
},
{
"name": "test3",
"name_format": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
"source": {
"name": "test3"
}
}
]
}
}
}
`)
}

createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
fullAccessApplication := AccessApplication{
ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db",
Name: "Admin Saas App",
Domain: "example.cloudflareaccess.com/cdn-cgi/access/sso/saml/737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893",
Type: "saas",
SessionDuration: "24h",
AUD: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893",
AllowedIdps: []string{},
AutoRedirectToIdentity: false,
EnableBindingCookie: false,
AppLauncherVisible: true,
ServiceAuth401Redirect: true,
CustomDenyMessage: "denied!",
CustomDenyURL: "https://www.example.com",
LogoURL: "https://www.example.com/example.png",
SkipInterstitial: true,
SaasApplication: &SaasApplication{
ConsumerServiceUrl: "https://saas.example.com",
SPEntityID: "dash.example.com",
NameIDFormat: "id",
CustomAttributes: []SAMLAttributeConfig{
{
Name: "test1",
NameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified",
Source: SourceConfig{
Name: "test1",
},
},
{
Name: "test2",
NameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:basic",
Source: SourceConfig{
Name: "test2",
},
},
{
Name: "test3",
NameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
Source: SourceConfig{
Name: "test3",
},
},
},
},
CreatedAt: &createdAt,
UpdatedAt: &updatedAt,
}

mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler)

actual, err := client.CreateAccessApplication(context.Background(), testAccountID, AccessApplication{
Name: "Admin Saas Site",
SaasApplication: &SaasApplication{
ConsumerServiceUrl: "https://examplesaas.com",
SPEntityID: "TEST12345678",
NameIDFormat: "id",
},
SessionDuration: "24h",
})

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

mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler)

actual, err = client.CreateZoneLevelAccessApplication(context.Background(), testZoneID, AccessApplication{
Name: "Admin Saas Site",
SaasApplication: &SaasApplication{
ConsumerServiceUrl: "https://saas.example.com",
SPEntityID: "TEST12345678",
NameIDFormat: "id",
},
SessionDuration: "24h",
})

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