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

Initial access config support #115

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

tomasliumparas
Copy link

@tomasliumparas tomasliumparas commented Dec 5, 2024

Initial AccessConfig version.
To do:

  • Use domain from TunnelBinding
  • Discuss if we should create AccessApplications before DNS records due to security reasons
  • Implement AccessPolicies calls

Currently tested with the following CRD:

apiVersion: networking.cfargotunnel.com/v1alpha1
kind: TunnelBinding
metadata:
  name: whoami-cluster-tun
subjects:
  - name: whoami
  - name: whoami-2 # Points to the second service
tunnelRef:
  kind: ClusterTunnel
  name: k3s-cluster-tunnel
accessConfig:
  name: whoami
  domain: whoami.domain.com
  type: "self_hosted"

#67

@tomasliumparas tomasliumparas changed the title #67 Initial access config support Initial access config support Dec 5, 2024
Copy link
Owner

@adyanth adyanth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Did you have a chance to test this out in your cluster to make sure it works? Had a couple questions/comments.

Comment on lines 241 to 267
// GatewayRules: []cloudflare.AccessApplicationGatewayRule{},
AllowedIdps: c.Settings.Authentication.AllowedIdps,
CustomDenyMessage: c.Settings.Authentication.CustomDenyMessage,
LogoURL: c.Settings.Appearance.CustomLogo,
// AUD: "",
Domain: hostname,
Type: cloudflare.AccessApplicationType(c.Type),
SessionDuration: c.Settings.Authentication.SessionDuration,
SameSiteCookieAttribute: c.Settings.Cookies.SameSiteAttribute,
CustomDenyURL: c.Settings.Authentication.CustomDenyUrl,
Name: hostname,
// PrivateAddress: "",
// CorsHeaders: &cloudflare.AccessApplicationCorsHeaders{
// AllowedMethods: []string{},
// AllowedOrigins: []string{},
// AllowedHeaders: []string{},
// AllowAllMethods: false,
// AllowAllHeaders: false,
// AllowAllOrigins: false,
// AllowCredentials: false,
// MaxAge: 0,
// },
// CreatedAt: &time.Time{},
// UpdatedAt: &time.Time{},
// SaasApplication: &cloudflare.SaasApplication{},
AutoRedirectToIdentity: &c.Settings.Authentication.InstantAuth,
// SkipInterstitial: new(bool),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why some are commented out? Could you remove them if they aren't needed, or are they needed in the future?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was planning to implement CORS support a bit later.
I can for sure remove the comments for now.

Copy link
Author

@tomasliumparas tomasliumparas Dec 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 7bde824

return ids, nil
}

func (c *CloudflareAPI) CreateAccessConfig(name string, config networkingv1alpha1.AccessConfig) error {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove the dependency of networkingv1alpha1 from this file by calling this function with the newApp already created and accepting an AccessApp instead?

Copy link
Author

@tomasliumparas tomasliumparas Dec 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is that I need to call CF api, to have it translated into AccessApp - basically to translate Access Group Names into ids.
That means I would need to include CloudflareAPI from cloudflare_api.go into tunnelbinding_types.go

Or I could move (c *AccessConfig) NewAccessApplication() into controllers package as a function.
I did this, since I originally wanted to have it as a method of AccessConfig. That way it is near the definition of the CRD and it makes a bit easier to map the fields.

Which way you would prefer more?

if len(config.AccessPolicies) == 0 {
c.Log.Info("deleting access policy for application", "applicationId", applicationId, "policyId", policy.ID)

err := c.CloudflareClient.DeleteAccessPolicy(ctx, accountId, applicationId, policy.ID)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this delete only the policies on this particular application?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Since existing policy list is fetched for current application

existingPolicies, _, err := c.CloudflareClient.AccessPolicies(ctx, accountId, applicationId, ...

c.Log.Error(err, "failed retrieving existing access policies for application", "applicationId", applicationId)
}

if len(existingPolicies) > 0 {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if condition is not necessary.

}

// Check if the policy is still required
required := false
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function seems convoluted. Let me phrase what I understand this function should be doing and you can correct me.

Given the set of existing access policies on the application, and the set of access policies defined in the CRD, you are trying to reconcile them. But there are a couple of problems. Does having the same name of the policy guarantee that the policy wasn't changed? Do we also create access groups here or just refer to them by name?

If possible, I'd like to see this split up into smaller functions and sync all the rules regardless of what was present, unless there was a way you could verify what is set online matches the local config.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one was a bit tricky.
What I am doing here is checking by name if there are any policies in the application, which are not defined in crd.
If yes, we delete them.

Later on we loop trough policies defined in crd and update them.

Cases I tested:

  • Policy by same name is changed manually, it should be updated to be matching crd configuration - works
  • Policy manually added to the ui, should be deleted - works
  • Policy should be deleted once gone from crd - works

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this makes sense?

@tomasliumparas
Copy link
Author

Thanks for the PR! Did you have a chance to test this out in your cluster to make sure it works? Had a couple questions/comments.

Yes, seem to work fine.
What I managed to test:

  • Creation/deletion of Access Applications with/without the policies
  • Changing order of access policies
  • Manually updating the policies via Cloudflare
  • Removing the policies via CRD
  • Renaming the policies via CRD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants