Skip to content
Open
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
13 changes: 13 additions & 0 deletions cmd/milo/controller-manager/controllermanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ var (
// EmailDomainJoiningRecheckInterval is how often an organization offering
// membership by email domain has its project Domains checked again.
EmailDomainJoiningRecheckInterval time.Duration
// OrganizationDomainRecordPrefix is the label in front of the domain in the
// TXT record name an OrganizationDomain asks its owners to add.
OrganizationDomainRecordPrefix string

// UserWaitlistPendingEmailTemplate is the template for the waitlist pending email.
UserWaitlistPendingEmailTemplate string
Expand Down Expand Up @@ -334,6 +337,7 @@ func NewCommand() *cobra.Command {
fs.StringVar(&AcceptInvitationRoleName, "accept-invitation-role-name", "iam.miloapis.com-acceptinvitation", "The name of the role that will be used to grant accept invitation permissions.")
fs.StringVar(&UserInvitationEmailTemplate, "user-invitation-email-template", "emailtemplates.notification.miloapis.com-userinvitationemailtemplate", "The name of the template that will be used to send the user invitation email.")
fs.DurationVar(&EmailDomainJoiningRecheckInterval, "email-domain-joining-recheck-interval", 10*time.Minute, "How often an organization that offers membership by email domain has its project Domains checked again. Only used when the EmailDomainJoining feature gate is enabled.")
fs.StringVar(&OrganizationDomainRecordPrefix, "organization-domain-record-prefix", resourcemanagercontroller.DefaultOrganizationDomainRecordPrefix, "The label in front of the domain in the DNS TXT record name that verifies an OrganizationDomain, such as _milo-verification for _milo-verification.acme.com. Only used when the EmailDomainJoining feature gate is enabled.")
fs.StringVar(&OrganizationMemberJoinedEmailTemplate, "organization-member-joined-email-template", "emailtemplates.notification.miloapis.com-organizationmemberjoinedemailtemplate", "The name of the template that will be used to tell organization owners that someone joined. Only used when the MemberJoinedEmails feature gate is enabled; set to an empty string to send no such emails.")
fs.StringVar(&UserWaitlistPendingEmailTemplate, "user-waitlist-pending-email-template", "emailtemplates.notification.miloapis.com-userwaitlistemailtemplate", "The name of the template that will be used to send the waitlist pending email.")
fs.StringVar(&UserWaitlistApprovedEmailTemplate, "user-waitlist-approved-email-template", "emailtemplates.notification.miloapis.com-userwelcomeemailtemplate", "The name of the template that will be used to send the waitlist approved email.")
Expand Down Expand Up @@ -809,6 +813,15 @@ func Run(ctx context.Context, c *config.CompletedConfig, opts *Options) error {
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}

organizationDomainCtrl := resourcemanagercontroller.OrganizationDomainController{
Client: ctrl.GetClient(),
RecordPrefix: OrganizationDomainRecordPrefix,
}
if err := organizationDomainCtrl.SetupWithManager(ctrl); err != nil {
logger.Error(err, "Error setting up organization domain controller")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}

noteCtrl := notescontroller.NoteController{
Client: ctrl.GetClient(),
CreatorEditorRoleName: NoteCreatorEditorRoleName,
Expand Down
3 changes: 3 additions & 0 deletions cmd/milo/controller-manager/webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ func registerCoreControlPlaneWebhooksWithoutNotes(mgr controllerruntime.Manager)
if err := resourcemanagerv1alpha1webhook.SetupOrganizationMembershipWebhooksWithManager(mgr, OrganizationOwnerRoleName, OrganizationOwnerRoleNamespace); err != nil {
return fmt.Errorf("setting up organizationmembership webhook: %w", err)
}
if err := resourcemanagerv1alpha1webhook.SetupOrganizationDomainWebhooksWithManager(mgr); err != nil {
return fmt.Errorf("setting up organizationdomain webhook: %w", err)
}
if err := iamv1alpha1webhook.SetupUserWebhooksWithManager(mgr, SystemNamespace, "iam-user-self-manage"); err != nil {
return fmt.Errorf("setting up user webhook: %w", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,23 +295,33 @@ rules:
- apiGroups:
- resourcemanager.miloapis.com
resources:
- organizationmemberships
- organizationdomains
- projectsuspensions
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- resourcemanager.miloapis.com
resources:
- organizationdomains/status
- organizationmemberships/status
- organizations/status
- projects/status
verbs:
- get
- patch
- update
- apiGroups:
- resourcemanager.miloapis.com
resources:
- organizationmemberships
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- resourcemanager.miloapis.com
resources:
Expand Down Expand Up @@ -340,11 +350,3 @@ rules:
- patch
- update
- watch
- apiGroups:
- resourcemanager.miloapis.com
resources:
- projectsuspensions
verbs:
- get
- list
- watch
1 change: 1 addition & 0 deletions config/crd/bases/resourcemanager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ resources:
- resourcemanager.miloapis.com_organizations.yaml
- resourcemanager.miloapis.com_projects.yaml
- resourcemanager.miloapis.com_organizationmemberships.yaml
- resourcemanager.miloapis.com_organizationdomains.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.22.0
discovery.miloapis.com/parent-contexts: Organization
name: organizationdomains.resourcemanager.miloapis.com
spec:
group: resourcemanager.miloapis.com
names:
kind: OrganizationDomain
listKind: OrganizationDomainList
plural: organizationdomains
singular: organizationdomain
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.domainName
name: Domain
type: string
- jsonPath: .status.conditions[?(@.type=='Verified')].status
name: Verified
type: string
- jsonPath: .status.verification.dnsRecord.name
name: Record
priority: 1
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: "OrganizationDomain proves that an organization controls a domain
name, such\nas the domain of its company's email addresses. It belongs to
the\norganization rather than to one of its projects, so the domain doesn't
have\nto be added to a project to be used.\n\nMilo publishes a DNS TXT record
in status.verification.dnsRecord. Once the\nrecord is found at the domain,
the Verified condition becomes True and stays\nTrue. The record can then
be removed.\n\nThe resource is named after its domain, so an organization
has at most one\nfor each domain. Verified domains, and their subdomains,
can be used for\nemail domain joining.\n\nExample:\n\n\tapiVersion: resourcemanager.miloapis.com/v1alpha1\n\tkind:
OrganizationDomain\n\tmetadata:\n\t name: acme.com\n\t namespace: organization-acme-corp\n\tspec:\n\t
\ domainName: acme.com"
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: OrganizationDomainSpec defines the domain an organization
wants to verify.
properties:
domainName:
description: |-
DomainName is the domain to verify, in lower case, such as acme.com or
eu.acme.com. It must match metadata.name and can't be changed.
maxLength: 253
minLength: 3
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+$
type: string
x-kubernetes-validations:
- message: domainName is immutable
rule: self == oldSelf
required:
- domainName
type: object
status:
description: OrganizationDomainStatus reports how verification is going.
properties:
conditions:
default:
- lastTransitionTime: "1970-01-01T00:00:00Z"
message: Waiting for the control plane to publish a verification
record
reason: Pending
status: Unknown
type: Verified
description: Conditions holds the Verified condition.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
verification:
description: |-
Verification holds the DNS record to add to the domain. It is cleared
once the domain is verified.
properties:
dnsRecord:
description: DNSRecord is the TXT record to add at the domain's
DNS provider.
properties:
content:
description: Content is the value the record must hold.
type: string
name:
description: |-
Name is the fully qualified record name, such as
_milo-verification.acme.com.
type: string
type:
description: Type is the record type. It is always TXT.
type: string
required:
- content
- name
- type
type: object
lastAttemptTime:
description: LastAttemptTime is when Milo last looked for the
record.
format: date-time
type: string
nextAttemptTime:
description: NextAttemptTime is when Milo will look for the record
again.
format: date-time
type: string
required:
- dnsRecord
type: object
type: object
required:
- spec
type: object
selectableFields:
- jsonPath: .spec.domainName
served: true
storage: true
subresources:
status: {}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ kind: Kustomization

resources:
- organization.yaml
- organizationdomain.yaml
- organizationmembership.yaml
- project.yaml
- projectsuspension.yaml
27 changes: 27 additions & 0 deletions config/protected-resources/resourcemanager/organizationdomain.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: iam.miloapis.com/v1alpha1
kind: ProtectedResource
metadata:
name: resourcemanager.miloapis.com-organizationdomain
spec:
serviceRef:
name: "resourcemanager.miloapis.com"
kind: OrganizationDomain
plural: organizationdomains
singular: organizationdomain
subresources:
- name: status
permissions:
- get
- update
- patch
permissions:
- list
- get
- create
- update
- delete
- patch
- watch
parentResources:
- apiGroup: resourcemanager.miloapis.com
kind: Organization
3 changes: 3 additions & 0 deletions config/roles/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ resources:
- notification-contact-group-enrollment-policy-reader.yaml
- notification-contact-group-enrollment-policy-editor.yaml
- notification-contact-group-enrollment-policy-admin.yaml
- organizationdomain-reader.yaml
- organizationdomain-editor.yaml
- organizationdomain-admin.yaml
- organizationmembership-reader.yaml
- organizationmembership-editor.yaml
- organizationmembership-admin.yaml
Expand Down
1 change: 1 addition & 0 deletions config/roles/organization-admin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ spec:
launchStage: Beta
inheritedRoles:
- name: organizationmembership-admin
- name: organizationdomain-admin
- name: resourcemanager.miloapis.com-organization-viewer
includedPermissions:
- resourcemanager.miloapis.com/organizations.create
Expand Down
1 change: 1 addition & 0 deletions config/roles/organization-viewer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ spec:
launchStage: Beta
inheritedRoles:
- name: organizationmembership-reader
- name: organizationdomain-reader
includedPermissions:
- resourcemanager.miloapis.com/organizations.get
- resourcemanager.miloapis.com/organizations/status.get
Expand Down
11 changes: 11 additions & 0 deletions config/roles/organizationdomain-admin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: iam.miloapis.com/v1alpha1
kind: Role
metadata:
name: organizationdomain-admin
annotations:
kubernetes.io/display-name: Organization Domain Admin
kubernetes.io/description: "Full access to an organization's domains"
spec:
launchStage: Beta
inheritedRoles:
- name: organizationdomain-editor
16 changes: 16 additions & 0 deletions config/roles/organizationdomain-editor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: iam.miloapis.com/v1alpha1
kind: Role
metadata:
name: organizationdomain-editor
annotations:
kubernetes.io/display-name: Organization Domain Editor
kubernetes.io/description: "Add and remove an organization's domains"
spec:
launchStage: Beta
inheritedRoles:
- name: organizationdomain-reader
includedPermissions:
- resourcemanager.miloapis.com/organizationdomains.create
- resourcemanager.miloapis.com/organizationdomains.update
- resourcemanager.miloapis.com/organizationdomains.patch
- resourcemanager.miloapis.com/organizationdomains.delete
Loading
Loading