1package cloudflare
2
3import (
4	"context"
5	"encoding/json"
6	"fmt"
7	"net/http"
8
9	"github.com/pkg/errors"
10)
11
12// AccessIdentityProvider is the structure of the provider object.
13type AccessIdentityProvider struct {
14	ID     string                              `json:"id,omitempty"`
15	Name   string                              `json:"name"`
16	Type   string                              `json:"type"`
17	Config AccessIdentityProviderConfiguration `json:"config"`
18}
19
20// AccessIdentityProviderConfiguration is the combined structure of *all*
21// identity provider configuration fields. This is done to simplify the use of
22// Access products and their relationship to each other.
23//
24// API reference: https://developers.cloudflare.com/access/configuring-identity-providers/
25type AccessIdentityProviderConfiguration struct {
26	APIToken           string   `json:"api_token,omitempty"`
27	AppsDomain         string   `json:"apps_domain,omitempty"`
28	Attributes         []string `json:"attributes,omitempty"`
29	AuthURL            string   `json:"auth_url,omitempty"`
30	CentrifyAccount    string   `json:"centrify_account,omitempty"`
31	CentrifyAppID      string   `json:"centrify_app_id,omitempty"`
32	CertsURL           string   `json:"certs_url,omitempty"`
33	ClientID           string   `json:"client_id,omitempty"`
34	ClientSecret       string   `json:"client_secret,omitempty"`
35	DirectoryID        string   `json:"directory_id,omitempty"`
36	EmailAttributeName string   `json:"email_attribute_name,omitempty"`
37	IdpPublicCert      string   `json:"idp_public_cert,omitempty"`
38	IssuerURL          string   `json:"issuer_url,omitempty"`
39	OktaAccount        string   `json:"okta_account,omitempty"`
40	OneloginAccount    string   `json:"onelogin_account,omitempty"`
41	RedirectURL        string   `json:"redirect_url,omitempty"`
42	SignRequest        bool     `json:"sign_request,omitempty"`
43	SsoTargetURL       string   `json:"sso_target_url,omitempty"`
44	SupportGroups      bool     `json:"support_groups,omitempty"`
45	TokenURL           string   `json:"token_url,omitempty"`
46}
47
48// AccessIdentityProvidersListResponse is the API response for multiple
49// Access Identity Providers.
50type AccessIdentityProvidersListResponse struct {
51	Response
52	Result []AccessIdentityProvider `json:"result"`
53}
54
55// AccessIdentityProviderListResponse is the API response for a single
56// Access Identity Provider.
57type AccessIdentityProviderListResponse struct {
58	Response
59	Result AccessIdentityProvider `json:"result"`
60}
61
62// AccessIdentityProviders returns all Access Identity Providers for an
63// account.
64//
65// API reference: https://api.cloudflare.com/#access-identity-providers-list-access-identity-providers
66func (api *API) AccessIdentityProviders(ctx context.Context, accountID string) ([]AccessIdentityProvider, error) {
67	return api.accessIdentityProviders(ctx, accountID, AccountRouteRoot)
68}
69
70// ZoneLevelAccessIdentityProviders returns all Access Identity Providers for an
71// account.
72//
73// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-list-access-identity-providers
74func (api *API) ZoneLevelAccessIdentityProviders(ctx context.Context, zoneID string) ([]AccessIdentityProvider, error) {
75	return api.accessIdentityProviders(ctx, zoneID, ZoneRouteRoot)
76}
77
78func (api *API) accessIdentityProviders(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessIdentityProvider, error) {
79	uri := fmt.Sprintf("/%s/%s/access/identity_providers", routeRoot, id)
80
81	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
82	if err != nil {
83		return []AccessIdentityProvider{}, err
84	}
85
86	var accessIdentityProviderResponse AccessIdentityProvidersListResponse
87	err = json.Unmarshal(res, &accessIdentityProviderResponse)
88	if err != nil {
89		return []AccessIdentityProvider{}, errors.Wrap(err, errUnmarshalError)
90	}
91
92	return accessIdentityProviderResponse.Result, nil
93}
94
95// AccessIdentityProviderDetails returns a single Access Identity
96// Provider for an account.
97//
98// API reference: https://api.cloudflare.com/#access-identity-providers-access-identity-providers-details
99func (api *API) AccessIdentityProviderDetails(ctx context.Context, accountID, identityProviderID string) (AccessIdentityProvider, error) {
100	return api.accessIdentityProviderDetails(ctx, accountID, identityProviderID, AccountRouteRoot)
101}
102
103// ZoneLevelAccessIdentityProviderDetails returns a single zone level Access Identity
104// Provider for an account.
105//
106// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-access-identity-providers-details
107func (api *API) ZoneLevelAccessIdentityProviderDetails(ctx context.Context, zoneID, identityProviderID string) (AccessIdentityProvider, error) {
108	return api.accessIdentityProviderDetails(ctx, zoneID, identityProviderID, ZoneRouteRoot)
109}
110
111func (api *API) accessIdentityProviderDetails(ctx context.Context, id string, identityProviderID string, routeRoot RouteRoot) (AccessIdentityProvider, error) {
112	uri := fmt.Sprintf(
113		"/%s/%s/access/identity_providers/%s",
114		routeRoot,
115		id,
116		identityProviderID,
117	)
118
119	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
120	if err != nil {
121		return AccessIdentityProvider{}, err
122	}
123
124	var accessIdentityProviderResponse AccessIdentityProviderListResponse
125	err = json.Unmarshal(res, &accessIdentityProviderResponse)
126	if err != nil {
127		return AccessIdentityProvider{}, errors.Wrap(err, errUnmarshalError)
128	}
129
130	return accessIdentityProviderResponse.Result, nil
131}
132
133// CreateAccessIdentityProvider creates a new Access Identity Provider.
134//
135// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider
136func (api *API) CreateAccessIdentityProvider(ctx context.Context, accountID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) {
137	return api.createAccessIdentityProvider(ctx, accountID, identityProviderConfiguration, AccountRouteRoot)
138}
139
140// CreateZoneLevelAccessIdentityProvider creates a new zone level Access Identity Provider.
141//
142// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-create-access-identity-provider
143func (api *API) CreateZoneLevelAccessIdentityProvider(ctx context.Context, zoneID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) {
144	return api.createAccessIdentityProvider(ctx, zoneID, identityProviderConfiguration, ZoneRouteRoot)
145}
146
147func (api *API) createAccessIdentityProvider(ctx context.Context, id string, identityProviderConfiguration AccessIdentityProvider, routeRoot RouteRoot) (AccessIdentityProvider, error) {
148	uri := fmt.Sprintf("/%s/%s/access/identity_providers", routeRoot, id)
149
150	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, identityProviderConfiguration)
151	if err != nil {
152		return AccessIdentityProvider{}, err
153	}
154
155	var accessIdentityProviderResponse AccessIdentityProviderListResponse
156	err = json.Unmarshal(res, &accessIdentityProviderResponse)
157	if err != nil {
158		return AccessIdentityProvider{}, errors.Wrap(err, errUnmarshalError)
159	}
160
161	return accessIdentityProviderResponse.Result, nil
162}
163
164// UpdateAccessIdentityProvider updates an existing Access Identity
165// Provider.
166//
167// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider
168func (api *API) UpdateAccessIdentityProvider(ctx context.Context, accountID, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) {
169	return api.updateAccessIdentityProvider(ctx, accountID, identityProviderUUID, identityProviderConfiguration, AccountRouteRoot)
170}
171
172// UpdateZoneLevelAccessIdentityProvider updates an existing zone level Access Identity
173// Provider.
174//
175// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-update-access-identity-provider
176func (api *API) UpdateZoneLevelAccessIdentityProvider(ctx context.Context, zoneID, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) {
177	return api.updateAccessIdentityProvider(ctx, zoneID, identityProviderUUID, identityProviderConfiguration, ZoneRouteRoot)
178}
179
180func (api *API) updateAccessIdentityProvider(ctx context.Context, id string, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider, routeRoot RouteRoot) (AccessIdentityProvider, error) {
181	uri := fmt.Sprintf(
182		"/%s/%s/access/identity_providers/%s",
183		routeRoot,
184		id,
185		identityProviderUUID,
186	)
187
188	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, identityProviderConfiguration)
189	if err != nil {
190		return AccessIdentityProvider{}, err
191	}
192
193	var accessIdentityProviderResponse AccessIdentityProviderListResponse
194	err = json.Unmarshal(res, &accessIdentityProviderResponse)
195	if err != nil {
196		return AccessIdentityProvider{}, errors.Wrap(err, errUnmarshalError)
197	}
198
199	return accessIdentityProviderResponse.Result, nil
200}
201
202// DeleteAccessIdentityProvider deletes an Access Identity Provider.
203//
204// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider
205func (api *API) DeleteAccessIdentityProvider(ctx context.Context, accountID, identityProviderUUID string) (AccessIdentityProvider, error) {
206	return api.deleteAccessIdentityProvider(ctx, accountID, identityProviderUUID, AccountRouteRoot)
207}
208
209// DeleteZoneLevelAccessIdentityProvider deletes a zone level Access Identity Provider.
210//
211// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-delete-access-identity-provider
212func (api *API) DeleteZoneLevelAccessIdentityProvider(ctx context.Context, zoneID, identityProviderUUID string) (AccessIdentityProvider, error) {
213	return api.deleteAccessIdentityProvider(ctx, zoneID, identityProviderUUID, ZoneRouteRoot)
214}
215
216func (api *API) deleteAccessIdentityProvider(ctx context.Context, id string, identityProviderUUID string, routeRoot RouteRoot) (AccessIdentityProvider, error) {
217	uri := fmt.Sprintf(
218		"/%s/%s/access/identity_providers/%s",
219		routeRoot,
220		id,
221		identityProviderUUID,
222	)
223
224	res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
225	if err != nil {
226		return AccessIdentityProvider{}, err
227	}
228
229	var accessIdentityProviderResponse AccessIdentityProviderListResponse
230	err = json.Unmarshal(res, &accessIdentityProviderResponse)
231	if err != nil {
232		return AccessIdentityProvider{}, errors.Wrap(err, errUnmarshalError)
233	}
234
235	return accessIdentityProviderResponse.Result, nil
236}
237