diff --git a/apis/cluster.cattle.io/v3/schema/schema.go b/apis/cluster.cattle.io/v3/schema/schema.go index c54b86c0..a1fff61a 100644 --- a/apis/cluster.cattle.io/v3/schema/schema.go +++ b/apis/cluster.cattle.io/v3/schema/schema.go @@ -3,6 +3,7 @@ package schema import ( "github.com/rancher/norman/types" m "github.com/rancher/norman/types/mapper" + "github.com/rancher/types/apis/cluster.cattle.io/v3" "github.com/rancher/types/factory" "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" @@ -20,7 +21,8 @@ var ( Schemas = factory.Schemas(&Version). Init(namespaceTypes). Init(persistentVolumeTypes). - Init(storageClassTypes) + Init(storageClassTypes). + Init(tokens) ) func namespaceTypes(schemas *types.Schemas) *types.Schemas { @@ -86,3 +88,15 @@ func storageClassTypes(schemas *types.Schemas) *types.Schemas { ReclaimPolicy string `json:"reclaimPolicy,omitempty" norman:"type=enum,options=Recycle|Delete|Retain"` }{}) } + +func tokens(schemas *types.Schemas) *types.Schemas { + return schemas. + MustImportAndCustomize(&Version, v3.ClusterAuthToken{}, func(schema *types.Schema) { + schema.CollectionMethods = []string{} + schema.ResourceMethods = []string{} + }). + MustImportAndCustomize(&Version, v3.ClusterUserAttribute{}, func(schema *types.Schema) { + schema.CollectionMethods = []string{} + schema.ResourceMethods = []string{} + }) +} diff --git a/apis/cluster.cattle.io/v3/types.go b/apis/cluster.cattle.io/v3/types.go new file mode 100644 index 00000000..dc709cbe --- /dev/null +++ b/apis/cluster.cattle.io/v3/types.go @@ -0,0 +1,30 @@ +package v3 + +import ( + "github.com/rancher/norman/types" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ClusterUserAttribute struct { + types.Namespaced + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Groups []string `json:"groups,omitempty"` + LastRefresh string `json:"lastRefresh,omitempty"` + NeedsRefresh bool `json:"needsRefresh"` + Enabled bool `json:"enabled"` +} + +type ClusterAuthToken struct { + types.Namespaced + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + UserName string `json:"userName"` + ExpiresAt string `json:"expiresAt,omitempty"` + SecretKeyHash string `json:"hash"` + Enabled bool `json:"enabled"` +} diff --git a/apis/management.cattle.io/v3/authn_types.go b/apis/management.cattle.io/v3/authn_types.go index c1a4ce50..ea95300c 100644 --- a/apis/management.cattle.io/v3/authn_types.go +++ b/apis/management.cattle.io/v3/authn_types.go @@ -25,6 +25,7 @@ type Token struct { Expired bool `json:"expired"` ExpiresAt string `json:"expiresAt"` Current bool `json:"current"` + ClusterName string `json:"clusterName,omitempty" norman:"noupdate,type=reference[cluster]"` Enabled *bool `json:"enabled,omitempty" norman:"default=true"` } diff --git a/apis/management.cattle.io/v3/cluster_types.go b/apis/management.cattle.io/v3/cluster_types.go index 8f604725..6313dbb3 100644 --- a/apis/management.cattle.io/v3/cluster_types.go +++ b/apis/management.cattle.io/v3/cluster_types.go @@ -77,6 +77,7 @@ type ClusterSpec struct { Description string `json:"description"` Internal bool `json:"internal" norman:"nocreate,noupdate"` DesiredAgentImage string `json:"desiredAgentImage"` + DesiredAuthImage string `json:"desiredAuthImage"` ImportedConfig *ImportedConfig `json:"importedConfig,omitempty" norman:"nocreate,noupdate"` GoogleKubernetesEngineConfig *MapStringInterface `json:"googleKubernetesEngineConfig,omitempty"` AzureKubernetesServiceConfig *MapStringInterface `json:"azureKubernetesServiceConfig,omitempty"` @@ -89,6 +90,9 @@ type ClusterSpec struct { EnableNetworkPolicy *bool `json:"enableNetworkPolicy" norman:"default=false"` EnableClusterAlerting bool `json:"enableClusterAlerting" norman:"default=false"` EnableClusterMonitoring bool `json:"enableClusterMonitoring" norman:"default=false"` + EnableClusterAuth bool `json:"enableClusterAuth" norman:"default=false"` + ClusterEndpointFQDN string `json:"clusterEndpointFQDN,omitempty"` + ClusterEndpointFQDNCaCert string `json:"clusterEndpointFQDNCaCert,omitempty"` } type ImportedConfig struct { @@ -103,6 +107,7 @@ type ClusterStatus struct { // https://kubernetes.io/docs/api-reference/v1.8/#componentstatus-v1-core Driver string `json:"driver"` AgentImage string `json:"agentImage"` + AuthImage string `json:"authImage"` ComponentStatuses []ClusterComponentStatus `json:"componentStatuses,omitempty"` APIEndpoint string `json:"apiEndpoint,omitempty"` ServiceAccountToken string `json:"serviceAccountToken,omitempty"` @@ -116,6 +121,7 @@ type ClusterStatus struct { Version *version.Info `json:"version,omitempty"` AppliedPodSecurityPolicyTemplateName string `json:"appliedPodSecurityPolicyTemplateId"` AppliedEnableNetworkPolicy bool `json:"appliedEnableNetworkPolicy" norman:"nocreate,noupdate,default=false"` + AppliedEnableClusterAuth bool `json:"appliedEnableAuth"` Capabilities Capabilities `json:"capabilities,omitempty"` MonitoringStatus *MonitoringStatus `json:"monitoringStatus,omitempty" norman:"nocreate,noupdate"` } diff --git a/apis/management.cattle.io/v3/rke_types.go b/apis/management.cattle.io/v3/rke_types.go index af4c9497..9be54680 100644 --- a/apis/management.cattle.io/v3/rke_types.go +++ b/apis/management.cattle.io/v3/rke_types.go @@ -256,13 +256,20 @@ type NetworkConfig struct { WeaveNetworkProvider *WeaveNetworkProvider `yaml:",omitempty" json:"weaveNetworkProvider,omitempty"` } +type AuthWebhookConfig struct { + // ConfigFile is a multiline string that represent a custom webhook config file + ConfigFile string `yaml:"config_file" json:"configFile,omitempty"` + // CacheTimeout controls how long to cache authentication decisions + CacheTimeout string `yaml:"cache_timeout" json:"cacheTimeout,omitempty"` +} + type AuthnConfig struct { // Authentication strategy that will be used in kubernetes cluster Strategy string `yaml:"strategy" json:"strategy,omitempty" norman:"default=x509"` - // Authentication options - Options map[string]string `yaml:"options" json:"options,omitempty"` // List of additional hostnames and IPs to include in the api server PKI cert SANs []string `yaml:"sans" json:"sans,omitempty"` + // Webhook configuration options + Webhook *AuthWebhookConfig `yaml:"webhook" json:"webhook,omitempty"` } type AuthzConfig struct { diff --git a/config/context.go b/config/context.go index 4ecd0146..58a26039 100644 --- a/config/context.go +++ b/config/context.go @@ -12,6 +12,7 @@ import ( appsv1beta2 "github.com/rancher/types/apis/apps/v1beta2" batchv1 "github.com/rancher/types/apis/batch/v1" batchv1beta1 "github.com/rancher/types/apis/batch/v1beta1" + clusterv3 "github.com/rancher/types/apis/cluster.cattle.io/v3" clusterSchema "github.com/rancher/types/apis/cluster.cattle.io/v3/schema" corev1 "github.com/rancher/types/apis/core/v1" extv1beta1 "github.com/rancher/types/apis/extensions/v1beta1" @@ -183,6 +184,7 @@ type UserContext struct { BatchV1Beta1 batchv1beta1.Interface Networking knetworkingv1.Interface Monitoring monitoringv1.Interface + Cluster clusterv3.Interface } func (w *UserContext) controllers() []controller.Starter { @@ -196,6 +198,7 @@ func (w *UserContext) controllers() []controller.Starter { w.BatchV1Beta1, w.Networking, w.Monitoring, + w.Cluster, } } @@ -215,6 +218,7 @@ func (w *UserContext) UserOnlyContext() *UserOnlyContext { BatchV1: w.BatchV1, BatchV1Beta1: w.BatchV1Beta1, Monitoring: w.Monitoring, + Cluster: w.Cluster, } } @@ -233,6 +237,7 @@ type UserOnlyContext struct { BatchV1 batchv1.Interface BatchV1Beta1 batchv1beta1.Interface Monitoring monitoringv1.Interface + Cluster clusterv3.Interface } func (w *UserOnlyContext) controllers() []controller.Starter { @@ -382,6 +387,7 @@ func NewUserContext(scaledContext *ScaledContext, config rest.Config, clusterNam } context.Monitoring, err = monitoringv1.NewForConfig(config) + context.Cluster, err = clusterv3.NewForConfig(config) if err != nil { return nil, err } @@ -465,6 +471,7 @@ func NewUserOnlyContext(config rest.Config) (*UserOnlyContext, error) { } context.Monitoring, err = monitoringv1.NewForConfig(config) + context.Cluster, err = clusterv3.NewForConfig(config) if err != nil { return nil, err } diff --git a/main.go b/main.go index 321954e2..f7a97a47 100644 --- a/main.go +++ b/main.go @@ -24,10 +24,13 @@ import ( func main() { generator.GenerateComposeType(projectSchema.Schemas, managementSchema.Schemas, clusterSchema.Schemas) generator.Generate(managementSchema.Schemas, map[string]bool{ - "userAttribute": true}, - ) + "userAttribute": true, + }) generator.Generate(publicSchema.PublicSchemas, nil) - generator.Generate(clusterSchema.Schemas, nil) + generator.Generate(clusterSchema.Schemas, map[string]bool{ + "clusterUserAttribute": true, + "clusterAuthToken": true, + }) generator.Generate(projectSchema.Schemas, nil) generator.GenerateNativeTypes(v1.SchemeGroupVersion, []interface{}{ v1.Endpoints{}, diff --git a/user/manager.go b/user/manager.go index 989863c1..6b263851 100644 --- a/user/manager.go +++ b/user/manager.go @@ -10,6 +10,7 @@ type Manager interface { SetPrincipalOnCurrentUser(apiContext *types.APIContext, principal v3.Principal) (*v3.User, error) GetUser(apiContext *types.APIContext) string EnsureToken(tokenName, description, userName string) (string, error) + EnsureClusterToken(clusterName, tokenName, description, userName string) (string, error) EnsureUser(principalName, displayName string) (*v3.User, error) CheckAccess(accessMode string, allowedPrincipalIDs []string, userPrincipalID string, groups []v3.Principal) (bool, error) SetPrincipalOnCurrentUserByUserID(userID string, principal v3.Principal) (*v3.User, error)