-
Notifications
You must be signed in to change notification settings - Fork 116
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
feat(update-security-json): Update security.json when secret is updated #744
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,12 +19,13 @@ package v1beta1 | |
|
||
import ( | ||
"fmt" | ||
"github.com/go-logr/logr" | ||
zkApi "github.com/pravega/zookeeper-operator/api/v1beta1" | ||
"math/rand" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/go-logr/logr" | ||
zkApi "github.com/pravega/zookeeper-operator/api/v1beta1" | ||
|
||
"k8s.io/apimachinery/pkg/util/intstr" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
|
@@ -681,7 +682,8 @@ type ManagedUpdateOptions struct { | |
// The maximum number of pods that can be unavailable during the update. | ||
// Value can be an absolute number (ex: 5) or a percentage of the desired number of pods (ex: 10%). | ||
// Absolute number is calculated from percentage by rounding down. | ||
// If the provided number is 0 or negative, then all pods will be allowed to be updated in unison. | ||
// If the provided number is 0, then all pods will be allowed to be updated in unison. | ||
// Negatives are not allowed. | ||
// | ||
// Defaults to 25%. | ||
// | ||
|
@@ -691,7 +693,8 @@ type ManagedUpdateOptions struct { | |
// The maximum number of replicas for each shard that can be unavailable during the update. | ||
// Value can be an absolute number (ex: 5) or a percentage of replicas in a shard (ex: 25%). | ||
// Absolute number is calculated from percentage by rounding down. | ||
// If the provided number is 0 or negative, then all replicas will be allowed to be updated in unison. | ||
// If the provided number is 0 , then all replicas will be allowed to be updated in unison. | ||
// Negatives are not allowed. | ||
// | ||
// Defaults to 1. | ||
// | ||
|
@@ -1621,6 +1624,15 @@ const ( | |
Basic AuthenticationType = "Basic" | ||
) | ||
|
||
type BootstrapSecurityJson struct { | ||
SecurityJsonSecret *corev1.SecretKeySelector `json:"bootstrapSecurityJson,omitempty"` | ||
|
||
// Flag to indicate if the operator should overwrite an existing security.json if there are changes | ||
// as compared to the underlying secret | ||
// +optional | ||
Overwrite bool `json:"overwrite,omitempty"` | ||
} | ||
|
||
type SolrSecurityOptions struct { | ||
// Indicates the authentication plugin type that is being used by Solr; for now only "Basic" is supported by the | ||
// Solr operator but support for other authentication plugins may be added in the future. | ||
|
@@ -1649,7 +1661,5 @@ type SolrSecurityOptions struct { | |
|
||
// Configure a user-provided security.json from a secret to allow for advanced security config. | ||
// If not specified, the operator bootstraps a security.json with basic auth enabled. | ||
// This is a bootstrapping config only; once Solr is initialized, the security config should be managed by the security API. | ||
// +optional | ||
BootstrapSecurityJson *corev1.SecretKeySelector `json:"bootstrapSecurityJson,omitempty"` | ||
BootstrapSecurityJson *BootstrapSecurityJson `json:"bootstrapSecurityJson,omitempty"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [0] I'm a bit torn on the CRD/interface for this functionality. Continuing to have "bootstrap" in the name feels a little misleading if this becomes something that isn't just about initial creation. But is it worth the hassle of deprecating this section and creating a nearly identical one with a clearer name, idk. Ignore my musing here, just thinking aloud. |
||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,19 +23,20 @@ import ( | |
b64 "encoding/base64" | ||
"encoding/json" | ||
"fmt" | ||
"math/rand" | ||
"regexp" | ||
"strings" | ||
"time" | ||
|
||
solr "github.com/apache/solr-operator/api/v1beta1" | ||
"github.com/apache/solr-operator/controllers/util/solr_api" | ||
appsv1 "k8s.io/api/apps/v1" | ||
corev1 "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
"math/rand" | ||
"regexp" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | ||
"strings" | ||
"time" | ||
) | ||
|
||
const ( | ||
|
@@ -49,10 +50,11 @@ const ( | |
// Utility struct holding security related config and objects resolved at runtime needed during reconciliation, | ||
// such as the secret holding credentials the operator should use to make calls to secure Solr | ||
type SecurityConfig struct { | ||
SolrSecurity *solr.SolrSecurityOptions | ||
CredentialsSecret *corev1.Secret | ||
SecurityJson string | ||
SecurityJsonSrc *corev1.EnvVarSource | ||
SolrSecurity *solr.SolrSecurityOptions | ||
CredentialsSecret *corev1.Secret | ||
SecurityJson string | ||
SecurityJsonSrc *corev1.EnvVarSource | ||
SecurityJsonOverwrite bool | ||
} | ||
|
||
// Given a SolrCloud instance and an API service client, produce a SecurityConfig needed to enable Solr security | ||
|
@@ -117,6 +119,7 @@ func reconcileForBasicAuthWithBootstrappedSecurityJson(ctx context.Context, clie | |
|
||
// supply the bootstrap security.json to the initContainer via a simple BASE64 encoding env var | ||
security.SecurityJson = string(bootstrapSecret.Data[SecurityJsonFile]) | ||
security.SecurityJsonOverwrite = false | ||
basicAuthSecret = authSecret | ||
} | ||
|
||
|
@@ -136,6 +139,7 @@ func reconcileForBasicAuthWithBootstrappedSecurityJson(ctx context.Context, clie | |
} else { | ||
// stash this so we can configure the setup-zk initContainer to bootstrap the security.json in ZK | ||
security.SecurityJson = string(bootstrapSecret.Data[SecurityJsonFile]) | ||
security.SecurityJsonOverwrite = false | ||
security.SecurityJsonSrc = &corev1.EnvVarSource{ | ||
SecretKeyRef: &corev1.SecretKeySelector{ | ||
LocalObjectReference: corev1.LocalObjectReference{Name: bootstrapSecret.Name}, Key: SecurityJsonFile}} | ||
|
@@ -166,13 +170,14 @@ func reconcileForBasicAuthWithUserProvidedSecret(ctx context.Context, client *cl | |
|
||
// is there a user-provided security.json in a secret? | ||
// in this config, we don't need to enforce the user providing a security.json as they can bootstrap the security.json however they want | ||
if sec.BootstrapSecurityJson != nil { | ||
securityJson, err := loadSecurityJsonFromSecret(ctx, client, sec.BootstrapSecurityJson, instance.Namespace) | ||
if sec.BootstrapSecurityJson != nil && sec.BootstrapSecurityJson.SecurityJsonSecret != nil { | ||
securityJson, err := loadSecurityJsonFromSecret(ctx, client, sec.BootstrapSecurityJson.SecurityJsonSecret, instance.Namespace) | ||
if err != nil { | ||
return nil, err | ||
} | ||
security.SecurityJson = securityJson | ||
security.SecurityJsonSrc = &corev1.EnvVarSource{SecretKeyRef: sec.BootstrapSecurityJson} | ||
security.SecurityJsonSrc = &corev1.EnvVarSource{SecretKeyRef: sec.BootstrapSecurityJson.SecurityJsonSecret} | ||
security.SecurityJsonOverwrite = sec.BootstrapSecurityJson.Overwrite | ||
} // else no user-provided secret, no sweat for us | ||
|
||
return security, nil | ||
|
@@ -240,11 +245,16 @@ func cmdToPutSecurityJsonInZk() string { | |
cmd := " solr zk cp zk:/security.json /tmp/current_security.json >/dev/null 2>&1; " + | ||
" GET_CURRENT_SECURITY_JSON_EXIT_CODE=$?; " + | ||
"if [ ${GET_CURRENT_SECURITY_JSON_EXIT_CODE} -eq 0 ]; then " + // JSON already exists | ||
"if [ ! -s /tmp/current_security.json ] || grep -q '^{}$' /tmp/current_security.json ]; then " + // File doesn't exist, is empty, or is just '{}' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Q] I guess the unmatched Anyways, great catch! |
||
"if [ ! -s /tmp/current_security.json ] || grep -q '^{}$' /tmp/current_security.json; then " + // File doesn't exist, is empty, or is just '{}' | ||
" echo $SECURITY_JSON > /tmp/security.json;" + | ||
" solr zk cp /tmp/security.json zk:/security.json >/dev/null 2>&1; " + | ||
" echo 'Blank security.json found. Put new security.json in ZK'; " + | ||
"fi; " + // TODO: Consider checking a diff and still applying over the top | ||
"elif [ \"${SECURITY_JSON_OVERWRITE}\" = true ] && [ \"$(cat /tmp/current_security.json)\" != \"$(echo $SECURITY_JSON)\" ]; then " + // We want to overwrite the security config if there's a diff | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Q] Am I reading this correctly, that the first two blocks both upload the JSON and only differ in the message they echo out? There might be a better way to structure that to avoid the duplication... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed that this bit of bash could probably be optimized. I don't immediately see a way of re-arranging the conditions. Maybe I can just create function that takes "message" as an input? |
||
" echo $SECURITY_JSON > /tmp/security.json;" + | ||
" solr zk cp /tmp/security.json zk:/security.json >/dev/null 2>&1; " + | ||
" echo 'Diff found. Overwriting security.json in ZK'; " + | ||
" else " + | ||
" echo 'Not overwriting security.json'; fi; " + | ||
"elif [ ${GET_CURRENT_SECURITY_JSON_EXIT_CODE} -eq 1 ]; then " + // JSON doesn't exist, but not other error types | ||
" echo $SECURITY_JSON > /tmp/security.json;" + | ||
" solr zk cp /tmp/security.json zk:/security.json >/dev/null 2>&1; " + | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[-0] If I'm reading this right, the YAML path for this property would be
.solrSecurity.bootstrapSecurityJson.bootstrapSecurityJson
?Would have to think a bit about how to fix it, but the redundancy there feels like it'd be confusing to users IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, this is a bit ugly. I'll wait for resolution on the naming change before changing this