Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f005b7537 | ||
|
|
1ad6e977f2 | ||
|
|
e9a64c5479 | ||
|
|
a2e7259ccb | ||
|
|
d28e66a353 | ||
|
|
e0ff6623bb | ||
|
|
3d59e9ac30 | ||
|
|
cff712f071 |
@@ -47,12 +47,12 @@ var serverCmd = cli.Command{
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tls-host",
|
||||
Value: restapi.GetSSLHostname(),
|
||||
Value: restapi.GetTLSHostname(),
|
||||
Usage: "HTTPS server hostname",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "tls-port",
|
||||
Value: restapi.GetSSLPort(),
|
||||
Value: restapi.GetTLSPort(),
|
||||
Usage: "HTTPS server port",
|
||||
},
|
||||
cli.StringFlag{
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.3.10
|
||||
image: minio/console:v0.3.13
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
args:
|
||||
- server
|
||||
|
||||
@@ -426,7 +426,7 @@ spec:
|
||||
externalCertSecret:
|
||||
description:
|
||||
ExternalCertSecret allows a user to specify custom
|
||||
CA certificate, and private key for group replication SSL.
|
||||
CA certificate, and private key for group replication TLS.
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.3.10
|
||||
image: minio/console:v0.3.13
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_OPERATOR_MODE
|
||||
|
||||
@@ -42,6 +42,9 @@ type CreateTenantRequest struct {
|
||||
// annotations
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
|
||||
// console image
|
||||
ConsoleImage string `json:"console_image,omitempty"`
|
||||
|
||||
// enable console
|
||||
EnableConsole *bool `json:"enable_console,omitempty"`
|
||||
|
||||
@@ -60,6 +63,9 @@ type CreateTenantRequest struct {
|
||||
// image
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// image pull secret
|
||||
ImagePullSecret string `json:"image_pull_secret,omitempty"`
|
||||
|
||||
// image registry
|
||||
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
||||
|
||||
|
||||
@@ -130,8 +130,8 @@ type IdpConfigurationActiveDirectory struct {
|
||||
// server insecure
|
||||
ServerInsecure bool `json:"server_insecure,omitempty"`
|
||||
|
||||
// skip ssl verification
|
||||
SkipSslVerification bool `json:"skip_ssl_verification,omitempty"`
|
||||
// skip tls verification
|
||||
SkipTLSVerification bool `json:"skip_tls_verification,omitempty"`
|
||||
|
||||
// url
|
||||
// Required: true
|
||||
|
||||
@@ -34,10 +34,17 @@ import (
|
||||
// swagger:model updateTenantRequest
|
||||
type UpdateTenantRequest struct {
|
||||
|
||||
// console image
|
||||
// Pattern: ^((.*?)/(.*?):(.+))$
|
||||
ConsoleImage string `json:"console_image,omitempty"`
|
||||
|
||||
// image
|
||||
// Pattern: ^((.*?)/(.*?):(.+))$
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// image pull secret
|
||||
ImagePullSecret string `json:"image_pull_secret,omitempty"`
|
||||
|
||||
// image registry
|
||||
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
||||
}
|
||||
@@ -46,6 +53,10 @@ type UpdateTenantRequest struct {
|
||||
func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateConsoleImage(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateImage(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
@@ -60,6 +71,19 @@ func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UpdateTenantRequest) validateConsoleImage(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.ConsoleImage) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := validate.Pattern("console_image", "body", string(m.ConsoleImage), `^((.*?)/(.*?):(.+))$`); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UpdateTenantRequest) validateImage(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.Image) { // not required
|
||||
|
||||
@@ -111,7 +111,7 @@ const AddTenant = ({
|
||||
const [accessKey, setAccessKey] = useState<string>("");
|
||||
const [secretKey, setSecretKey] = useState<string>("");
|
||||
const [enableConsole, setEnableConsole] = useState<boolean>(true);
|
||||
const [enableSSL, setEnableSSL] = useState<boolean>(false);
|
||||
const [enableTLS, setEnableTLS] = useState<boolean>(false);
|
||||
const [sizeFactor, setSizeFactor] = useState<string>("Gi");
|
||||
const [storageClasses, setStorageClassesList] = useState<Opts[]>([]);
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
@@ -274,7 +274,7 @@ const AddTenant = ({
|
||||
name: tenantName,
|
||||
service_name: tenantName,
|
||||
image: imageName,
|
||||
enable_ssl: enableSSL,
|
||||
enable_tls: enableTLS,
|
||||
enable_console: enableConsole,
|
||||
access_key: accessKey,
|
||||
secret_key: secretKey,
|
||||
@@ -750,17 +750,17 @@ const AddTenant = ({
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<CheckboxWrapper
|
||||
value="enable_ssl"
|
||||
id="enable_ssl"
|
||||
name="enable_ssl"
|
||||
checked={enableSSL}
|
||||
value="enable_tls"
|
||||
id="enable_tls"
|
||||
name="enable_tls"
|
||||
checked={enableTLS}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
|
||||
setEnableSSL(checked);
|
||||
setEnableTLS(checked);
|
||||
}}
|
||||
label={"Enable SSL"}
|
||||
label={"Enable TLS"}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
@@ -882,9 +882,9 @@ const AddTenant = ({
|
||||
<React.Fragment>
|
||||
<TableRow>
|
||||
<TableCell align="right" className={classes.tableTitle}>
|
||||
Enable SSL
|
||||
Enable TLS
|
||||
</TableCell>
|
||||
<TableCell>{enableSSL ? "Enabled" : "Disabled"}</TableCell>
|
||||
<TableCell>{enableTLS ? "Enabled" : "Disabled"}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell align="right" className={classes.tableTitle}>
|
||||
|
||||
@@ -54,10 +54,6 @@ import (
|
||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
minioRegCred = "minio-regcred-secret"
|
||||
)
|
||||
|
||||
type imageRegistry struct {
|
||||
Auths map[string]imageRegistryCredentials `json:"auths"`
|
||||
}
|
||||
@@ -345,10 +341,10 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
|
||||
if minioImage == "" {
|
||||
minImg, err := cluster.GetMinioImage()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// we can live without figuring out the latest version of MinIO, Operator will use a hardcoded value
|
||||
if err == nil {
|
||||
minioImage = *minImg
|
||||
}
|
||||
minioImage = *minImg
|
||||
}
|
||||
// get Kubernetes Client
|
||||
clientset, err := cluster.K8sClient(session.SessionToken)
|
||||
@@ -420,7 +416,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
url := *tenantReq.Idp.ActiveDirectory.URL
|
||||
userNameFormat := *tenantReq.Idp.ActiveDirectory.UsernameFormat
|
||||
userSearchFilter := *tenantReq.Idp.ActiveDirectory.UserSearchFilter
|
||||
tlsSkipVerify := tenantReq.Idp.ActiveDirectory.SkipSslVerification
|
||||
tlsSkipVerify := tenantReq.Idp.ActiveDirectory.SkipTLSVerification
|
||||
serverInsecure := tenantReq.Idp.ActiveDirectory.ServerInsecure
|
||||
groupSearchDN := tenantReq.Idp.ActiveDirectory.GroupSearchBaseDn
|
||||
groupSearchFilter := tenantReq.Idp.ActiveDirectory.GroupSearchFilter
|
||||
@@ -467,7 +463,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
|
||||
isEncryptionAvailable := false
|
||||
if *tenantReq.EnableTLS {
|
||||
if tenantReq.EnableTLS != nil && *tenantReq.EnableTLS {
|
||||
// If user request autoCert, Operator will generate certificate keypair for MinIO (server), Console (server) and KES (server and app mTLS)
|
||||
isEncryptionAvailable = true
|
||||
minInst.Spec.RequestAutoCert = *tenantReq.EnableTLS
|
||||
@@ -536,8 +532,10 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
var consoleAccess string
|
||||
var consoleSecret string
|
||||
|
||||
//enableConsole := true
|
||||
enableConsole := *tenantReq.EnableConsole
|
||||
enableConsole := true
|
||||
if tenantReq.EnableConsole != nil && *tenantReq.EnableConsole {
|
||||
enableConsole = *tenantReq.EnableConsole
|
||||
}
|
||||
|
||||
if enableConsole {
|
||||
consoleSelector := fmt.Sprintf("%s-console", *tenantReq.Name)
|
||||
@@ -585,9 +583,9 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
return nil, err
|
||||
}
|
||||
|
||||
const consoleVersion = "minio/console:v0.3.10"
|
||||
const consoleVersion = "minio/console:v0.3.13"
|
||||
minInst.Spec.Console = &operator.ConsoleConfiguration{
|
||||
Replicas: 2,
|
||||
Replicas: 1,
|
||||
Image: consoleVersion,
|
||||
ConsoleSecret: &corev1.LocalObjectReference{Name: consoleSecretName},
|
||||
Resources: corev1.ResourceRequirements{
|
||||
@@ -597,7 +595,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
},
|
||||
}
|
||||
|
||||
if !minInst.Spec.RequestAutoCert && tenantReq.TLS.Console != nil {
|
||||
if !minInst.Spec.RequestAutoCert && tenantReq.TLS != nil && tenantReq.TLS.Console != nil {
|
||||
consoleExternalTLSCertificateSecretName := fmt.Sprintf("%s-console-external-certificates", secretName)
|
||||
tlsCrt, err := base64.StdEncoding.DecodeString(*tenantReq.TLS.Console.Crt)
|
||||
if err != nil {
|
||||
@@ -658,13 +656,25 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
minInst.Spec.Mountpath = tenantReq.MounthPath
|
||||
}
|
||||
|
||||
if err := setImageRegistry(ctx, tenantReq.ImageRegistry, clientset.CoreV1(), ns); err != nil {
|
||||
// We accept either `image_pull_secret` or the individual details of the `image_registry` but not both
|
||||
var imagePullSecret string
|
||||
|
||||
if tenantReq.ImagePullSecret != "" {
|
||||
imagePullSecret = tenantReq.ImagePullSecret
|
||||
} else if imagePullSecret, err = setImageRegistry(ctx, *tenantReq.Name, tenantReq.ImageRegistry, clientset.CoreV1(), ns); err != nil {
|
||||
log.Println("error setting image registry secret:", err)
|
||||
return nil, err
|
||||
}
|
||||
// pass the image pull secret to the Tenant
|
||||
if imagePullSecret != "" {
|
||||
minInst.Spec.ImagePullSecret = corev1.LocalObjectReference{
|
||||
Name: imagePullSecret,
|
||||
}
|
||||
}
|
||||
|
||||
minInst.Spec.ImagePullSecret = corev1.LocalObjectReference{
|
||||
Name: minioRegCred,
|
||||
// set console image if provided
|
||||
if tenantReq.ConsoleImage != "" {
|
||||
minInst.Spec.Console.Image = tenantReq.ConsoleImage
|
||||
}
|
||||
|
||||
opClient, err := cluster.OperatorClient(session.SessionToken)
|
||||
@@ -698,9 +708,11 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func setImageRegistry(ctx context.Context, req *models.ImageRegistry, clientset v1.CoreV1Interface, namespace string) error {
|
||||
// setImageRegistry creates a secret to store the private registry credentials, if one exist it updates the existing one
|
||||
// returns the name of the secret created/updated
|
||||
func setImageRegistry(ctx context.Context, tenantName string, req *models.ImageRegistry, clientset v1.CoreV1Interface, namespace string) (string, error) {
|
||||
if req == nil || req.Registry == nil || req.Username == nil || req.Password == nil {
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
|
||||
credentials := make(map[string]imageRegistryCredentials)
|
||||
@@ -718,12 +730,14 @@ func setImageRegistry(ctx context.Context, req *models.ImageRegistry, clientset
|
||||
}
|
||||
imRegistryJSON, err := json.Marshal(imRegistry)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
pullSecretName := fmt.Sprintf("%s-regcred", tenantName)
|
||||
|
||||
instanceSecret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: minioRegCred,
|
||||
Name: pullSecretName,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
corev1.DockerConfigJsonKey: []byte(string(imRegistryJSON)),
|
||||
@@ -732,22 +746,22 @@ func setImageRegistry(ctx context.Context, req *models.ImageRegistry, clientset
|
||||
}
|
||||
|
||||
// Get or Create secret if it doesn't exist
|
||||
_, err = clientset.Secrets(namespace).Get(ctx, minioRegCred, metav1.GetOptions{})
|
||||
_, err = clientset.Secrets(namespace).Get(ctx, pullSecretName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if k8sErrors.IsNotFound(err) {
|
||||
_, err = clientset.Secrets(namespace).Create(ctx, &instanceSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
_, err = clientset.Secrets(namespace).Update(ctx, &instanceSecret, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
return nil
|
||||
return pullSecretName, nil
|
||||
}
|
||||
|
||||
// updateTenantAction does an update on the minioTenant by patching the desired changes
|
||||
@@ -755,25 +769,35 @@ func updateTenantAction(ctx context.Context, operatorClient OperatorClient, clie
|
||||
imageToUpdate := params.Body.Image
|
||||
imageRegistryReq := params.Body.ImageRegistry
|
||||
|
||||
if err := setImageRegistry(ctx, imageRegistryReq, clientset, namespace); err != nil {
|
||||
log.Println("error setting image registry secret:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
minInst, err := operatorClient.TenantGet(ctx, namespace, params.Tenant, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// we can take either the `image_pull_secret` of the `image_registry` but not both
|
||||
if params.Body.ImagePullSecret != "" {
|
||||
minInst.Spec.ImagePullSecret.Name = params.Body.ImagePullSecret
|
||||
} else {
|
||||
// update the image pull secret content
|
||||
if _, err := setImageRegistry(ctx, params.Tenant, imageRegistryReq, clientset, namespace); err != nil {
|
||||
log.Println("error setting image registry secret:", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// update the console image
|
||||
if strings.TrimSpace(params.Body.ConsoleImage) != "" && minInst.Spec.Console != nil {
|
||||
minInst.Spec.Console.Image = params.Body.ConsoleImage
|
||||
}
|
||||
|
||||
// if image to update is empty we'll use the latest image by default
|
||||
if strings.TrimSpace(imageToUpdate) != "" {
|
||||
minInst.Spec.Image = imageToUpdate
|
||||
} else {
|
||||
im, err := cluster.GetLatestMinioImage(httpCl)
|
||||
if err != nil {
|
||||
return err
|
||||
// if we can't get the MinIO image, we won' auto-update it unless it's explicit by name
|
||||
if err == nil {
|
||||
minInst.Spec.Image = *im
|
||||
}
|
||||
minInst.Spec.Image = *im
|
||||
}
|
||||
|
||||
payloadBytes, err := json.Marshal(minInst)
|
||||
|
||||
@@ -647,6 +647,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
return &http.Response{}, nil
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Tenant: "minio-tenant",
|
||||
Body: &models.UpdateTenantRequest{
|
||||
Image: "minio/minio:RELEASE.2020-06-03T22-13-49Z",
|
||||
},
|
||||
@@ -675,6 +676,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Tenant: "minio-tenant",
|
||||
Body: &models.UpdateTenantRequest{
|
||||
Image: "",
|
||||
},
|
||||
@@ -683,7 +685,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Empty image input Error retrieving latest image",
|
||||
name: "Empty image input Error retrieving latest image, nothing happens",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
@@ -700,12 +702,63 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
return nil, errors.New("error")
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Tenant: "minio-tenant",
|
||||
Body: &models.UpdateTenantRequest{
|
||||
Image: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Update minio console version no errors",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
httpCl: httpClientM,
|
||||
nameSpace: "default",
|
||||
tenantName: "minio-tenant",
|
||||
mockTenantPatch: func(ctx context.Context, namespace string, tenantName string, pt types.PatchType, data []byte, options metav1.PatchOptions) (*v1.Tenant, error) {
|
||||
return &v1.Tenant{}, nil
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*v1.Tenant, error) {
|
||||
return &v1.Tenant{}, nil
|
||||
},
|
||||
mockHTTPClientGet: func(url string) (resp *http.Response, err error) {
|
||||
return nil, errors.New("use default minio")
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Body: &models.UpdateTenantRequest{
|
||||
ConsoleImage: "minio/console:v0.3.13",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Update minio image pull secrets no errors",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
httpCl: httpClientM,
|
||||
nameSpace: "default",
|
||||
tenantName: "minio-tenant",
|
||||
mockTenantPatch: func(ctx context.Context, namespace string, tenantName string, pt types.PatchType, data []byte, options metav1.PatchOptions) (*v1.Tenant, error) {
|
||||
return &v1.Tenant{}, nil
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*v1.Tenant, error) {
|
||||
return &v1.Tenant{}, nil
|
||||
},
|
||||
mockHTTPClientGet: func(url string) (resp *http.Response, err error) {
|
||||
return nil, errors.New("use default minio")
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Body: &models.UpdateTenantRequest{
|
||||
ImagePullSecret: "minio-regcred",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -249,7 +249,7 @@ func newMinioClient(claims *models.Principal) (*minio.Client, error) {
|
||||
// newS3BucketClient creates a new mc S3Client to talk to the server based on a bucket
|
||||
func newS3BucketClient(claims *models.Principal, bucketName string) (*mc.S3Client, error) {
|
||||
endpoint := getMinIOServer()
|
||||
useSSL := getMinIOEndpointIsSecure()
|
||||
useTLS := getMinIOEndpointIsSecure()
|
||||
|
||||
if strings.TrimSpace(bucketName) != "" {
|
||||
endpoint += fmt.Sprintf("/%s", bucketName)
|
||||
@@ -259,7 +259,7 @@ func newS3BucketClient(claims *models.Principal, bucketName string) (*mc.S3Clien
|
||||
return nil, fmt.Errorf("the provided credentials are invalid")
|
||||
}
|
||||
|
||||
s3Config := newS3Config(endpoint, claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken, !useSSL)
|
||||
s3Config := newS3Config(endpoint, claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken, !useTLS)
|
||||
client, pErr := mc.S3New(s3Config)
|
||||
if pErr != nil {
|
||||
return nil, pErr.Cause
|
||||
|
||||
@@ -105,15 +105,15 @@ func GetPort() int {
|
||||
return port
|
||||
}
|
||||
|
||||
// GetSSLHostname gets console ssl hostname set on env variable
|
||||
// GetTLSHostname gets console tls hostname set on env variable
|
||||
// or default one
|
||||
func GetSSLHostname() string {
|
||||
func GetTLSHostname() string {
|
||||
return strings.ToLower(env.Get(ConsoleTLSHostname, TLSHostname))
|
||||
}
|
||||
|
||||
// GetSSLPort gets console ssl port set on env variable
|
||||
// GetTLSPort gets console tls port set on env variable
|
||||
// or default one
|
||||
func GetSSLPort() int {
|
||||
func GetTLSPort() int {
|
||||
port, err := strconv.Atoi(env.Get(ConsoleTLSPort, TLSPort))
|
||||
if err != nil {
|
||||
port = 9443
|
||||
@@ -171,14 +171,14 @@ func getSecureHostsProxyHeaders() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// If SSLRedirect is set to true, then only allow HTTPS requests. Default is true.
|
||||
func getSSLRedirect() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureSSLRedirect, TLSRedirect)) == "on"
|
||||
// If TLSRedirect is set to true, then only allow HTTPS requests. Default is true.
|
||||
func getTLSRedirect() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureTLSRedirect, TLSRedirect)) == "on"
|
||||
}
|
||||
|
||||
// SSLHost is the host name that is used to redirect HTTP requests to HTTPS. Default is "", which indicates to use the same host.
|
||||
func getSecureSSLHost() string {
|
||||
return env.Get(ConsoleSecureSSLHost, fmt.Sprintf("%s:%s", TLSHostname, TLSPort))
|
||||
// TLSHost is the host name that is used to redirect HTTP requests to HTTPS. Default is "", which indicates to use the same host.
|
||||
func getSecureTLSHost() string {
|
||||
return env.Get(ConsoleSecureTLSHost, fmt.Sprintf("%s:%s", TLSHostname, TLSPort))
|
||||
}
|
||||
|
||||
// STSSeconds is the max-age of the Strict-Transport-Security header. Default is 0, which would NOT include the header.
|
||||
@@ -200,9 +200,9 @@ func getSecureSTSPreload() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureSTSPreload, "off")) == "on"
|
||||
}
|
||||
|
||||
// If SSLTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301).
|
||||
func getSecureSSLTemporaryRedirect() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureSSLTemporaryRedirect, "off")) == "on"
|
||||
// If TLSTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301).
|
||||
func getSecureTLSTemporaryRedirect() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureTLSTemporaryRedirect, "off")) == "on"
|
||||
}
|
||||
|
||||
// STS header is only included when the connection is HTTPS.
|
||||
|
||||
@@ -149,12 +149,12 @@ func setupGlobalMiddleware(handler http.Handler) http.Handler {
|
||||
AllowedHosts: getSecureAllowedHosts(),
|
||||
AllowedHostsAreRegex: getSecureAllowedHostsAreRegex(),
|
||||
HostsProxyHeaders: getSecureHostsProxyHeaders(),
|
||||
SSLRedirect: getSSLRedirect(),
|
||||
SSLHost: getSecureSSLHost(),
|
||||
SSLRedirect: getTLSRedirect(),
|
||||
SSLHost: getSecureTLSHost(),
|
||||
STSSeconds: getSecureSTSSeconds(),
|
||||
STSIncludeSubdomains: getSecureSTSIncludeSubdomains(),
|
||||
STSPreload: getSecureSTSPreload(),
|
||||
SSLTemporaryRedirect: getSecureSSLTemporaryRedirect(),
|
||||
SSLTemporaryRedirect: getSecureTLSTemporaryRedirect(),
|
||||
SSLHostFunc: nil,
|
||||
ForceSTSHeader: getSecureForceSTSHeader(),
|
||||
FrameDeny: getSecureFrameDeny(),
|
||||
|
||||
@@ -41,9 +41,9 @@ const (
|
||||
ConsoleSecureSTSSeconds = "CONSOLE_SECURE_STS_SECONDS"
|
||||
ConsoleSecureSTSIncludeSubdomains = "CONSOLE_SECURE_STS_INCLUDE_SUB_DOMAINS"
|
||||
ConsoleSecureSTSPreload = "CONSOLE_SECURE_STS_PRELOAD"
|
||||
ConsoleSecureSSLRedirect = "CONSOLE_SECURE_SSL_REDIRECT"
|
||||
ConsoleSecureSSLHost = "CONSOLE_SECURE_SSL_HOST"
|
||||
ConsoleSecureSSLTemporaryRedirect = "CONSOLE_SECURE_SSL_TEMPORARY_REDIRECT"
|
||||
ConsoleSecureTLSRedirect = "CONSOLE_SECURE_TLS_REDIRECT"
|
||||
ConsoleSecureTLSHost = "CONSOLE_SECURE_TLS_HOST"
|
||||
ConsoleSecureTLSTemporaryRedirect = "CONSOLE_SECURE_TLS_TEMPORARY_REDIRECT"
|
||||
ConsoleSecureForceSTSHeader = "CONSOLE_SECURE_FORCE_STS_HEADER"
|
||||
ConsoleSecurePublicKey = "CONSOLE_SECURE_PUBLIC_KEY"
|
||||
ConsoleSecureReferrerPolicy = "CONSOLE_SECURE_REFERRER_POLICY"
|
||||
|
||||
@@ -2024,6 +2024,9 @@ func init() {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"console_image": {
|
||||
"type": "string"
|
||||
},
|
||||
"enable_console": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
@@ -2046,6 +2049,9 @@ func init() {
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_pull_secret": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_registry": {
|
||||
"$ref": "#/definitions/imageRegistry"
|
||||
},
|
||||
@@ -2235,7 +2241,7 @@ func init() {
|
||||
"server_insecure": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skip_ssl_verification": {
|
||||
"skip_tls_verification": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"url": {
|
||||
@@ -3059,10 +3065,17 @@ func init() {
|
||||
"updateTenantRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"console_image": {
|
||||
"type": "string",
|
||||
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||
},
|
||||
"image": {
|
||||
"type": "string",
|
||||
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||
},
|
||||
"image_pull_secret": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_registry": {
|
||||
"$ref": "#/definitions/imageRegistry"
|
||||
}
|
||||
@@ -5341,7 +5354,7 @@ func init() {
|
||||
"server_insecure": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skip_ssl_verification": {
|
||||
"skip_tls_verification": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"url": {
|
||||
@@ -5938,6 +5951,9 @@ func init() {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"console_image": {
|
||||
"type": "string"
|
||||
},
|
||||
"enable_console": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
@@ -5960,6 +5976,9 @@ func init() {
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_pull_secret": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_registry": {
|
||||
"$ref": "#/definitions/imageRegistry"
|
||||
},
|
||||
@@ -6149,7 +6168,7 @@ func init() {
|
||||
"server_insecure": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skip_ssl_verification": {
|
||||
"skip_tls_verification": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"url": {
|
||||
@@ -6907,10 +6926,17 @@ func init() {
|
||||
"updateTenantRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"console_image": {
|
||||
"type": "string",
|
||||
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||
},
|
||||
"image": {
|
||||
"type": "string",
|
||||
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||
},
|
||||
"image_pull_secret": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_registry": {
|
||||
"$ref": "#/definitions/imageRegistry"
|
||||
}
|
||||
|
||||
@@ -19,16 +19,30 @@ package restapi
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
certDontExists = "File certificate doesn't exists: %s"
|
||||
)
|
||||
func getCertPool() *x509.CertPool {
|
||||
caCertFileNames := getMinioServerTLSRootCAs()
|
||||
// If CAs certificates are configured we save them to the http.Client RootCAs store
|
||||
certs := x509.NewCertPool()
|
||||
for _, caCert := range caCertFileNames {
|
||||
pemData, err := ioutil.ReadFile(caCert)
|
||||
if err != nil {
|
||||
// logging this error
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
certs.AppendCertsFromPEM(pemData)
|
||||
}
|
||||
return certs
|
||||
}
|
||||
|
||||
var certPool = getCertPool()
|
||||
|
||||
func prepareSTSClientTransport(insecure bool) *http.Transport {
|
||||
// This takes github.com/minio/minio/pkg/madmin/transport.go as an example
|
||||
@@ -36,18 +50,6 @@ func prepareSTSClientTransport(insecure bool) *http.Transport {
|
||||
// DefaultTransport - this default transport is similar to
|
||||
// http.DefaultTransport but with additional param DisableCompression
|
||||
// is set to true to avoid decompressing content with 'gzip' encoding.
|
||||
|
||||
// Keep TLS config.
|
||||
tlsConfig := &tls.Config{
|
||||
// Can't use SSLv3 because of POODLE and BEAST
|
||||
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
|
||||
// Can't use TLSv1.1 because of RC4 cipher usage
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
if insecure {
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
}
|
||||
|
||||
DefaultTransport := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
@@ -61,38 +63,14 @@ func prepareSTSClientTransport(insecure bool) *http.Transport {
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
DisableCompression: true,
|
||||
TLSClientConfig: tlsConfig,
|
||||
}
|
||||
// If Minio instance is running with TLS enabled and it's using a self-signed certificate
|
||||
// or a certificate issued by a custom certificate authority we prepare a new custom *http.Transport
|
||||
if getMinIOEndpointIsSecure() {
|
||||
caCertFileNames := getMinioServerTLSRootCAs()
|
||||
tlsConfig := &tls.Config{
|
||||
TLSClientConfig: &tls.Config{
|
||||
// Can't use SSLv3 because of POODLE and BEAST
|
||||
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
|
||||
// Can't use TLSv1.1 because of RC4 cipher usage
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
// If CAs certificates are configured we save them to the http.Client RootCAs store
|
||||
if len(caCertFileNames) > 0 {
|
||||
certs := x509.NewCertPool()
|
||||
for _, caCert := range caCertFileNames {
|
||||
// Validate certificate exists
|
||||
if FileExists(caCert) {
|
||||
pemData, err := ioutil.ReadFile(caCert)
|
||||
if err != nil {
|
||||
// if there was an error reading pem file stop console
|
||||
panic(err)
|
||||
}
|
||||
certs.AppendCertsFromPEM(pemData)
|
||||
} else {
|
||||
// if provided cert filename doesn't exists stop console
|
||||
panic(fmt.Sprintf(certDontExists, caCert))
|
||||
}
|
||||
}
|
||||
tlsConfig.RootCAs = certs
|
||||
}
|
||||
DefaultTransport.TLSClientConfig = tlsConfig
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: insecure,
|
||||
RootCAs: certPool,
|
||||
},
|
||||
}
|
||||
return DefaultTransport
|
||||
}
|
||||
|
||||
11
swagger.yml
11
swagger.yml
@@ -1778,8 +1778,13 @@ definitions:
|
||||
image:
|
||||
type: string
|
||||
pattern: "^((.*?)/(.*?):(.+))$"
|
||||
console_image:
|
||||
type: string
|
||||
pattern: "^((.*?)/(.*?):(.+))$"
|
||||
image_registry:
|
||||
$ref: "#/definitions/imageRegistry"
|
||||
image_pull_secret:
|
||||
type: string
|
||||
|
||||
imageRegistry:
|
||||
type: object
|
||||
@@ -1807,6 +1812,8 @@ definitions:
|
||||
pattern: "^[a-z0-9-]{3,63}$"
|
||||
image:
|
||||
type: string
|
||||
console_image:
|
||||
type: string
|
||||
service_name:
|
||||
type: string
|
||||
zones:
|
||||
@@ -1835,6 +1842,8 @@ definitions:
|
||||
type: string
|
||||
image_registry:
|
||||
$ref: "#/definitions/imageRegistry"
|
||||
image_pull_secret:
|
||||
type: string
|
||||
idp:
|
||||
type: object
|
||||
$ref: "#/definitions/idpConfiguration"
|
||||
@@ -1901,7 +1910,7 @@ definitions:
|
||||
type: string
|
||||
group_name_attribute:
|
||||
type: string
|
||||
skip_ssl_verification:
|
||||
skip_tls_verification:
|
||||
type: boolean
|
||||
server_insecure:
|
||||
type: boolean
|
||||
|
||||
Reference in New Issue
Block a user