@ -130,44 +130,51 @@ func (cfg *settings) setupKube(ctx context.Context) error {
}
canPatch , canCreate , err := kc . CheckSecretPermissions ( ctx , cfg . KubeSecret )
if err != nil {
return fmt . Errorf ( " S ome Kubernetes permissions are missing, please check your RBAC configuration: %v", err )
return fmt . Errorf ( " s ome Kubernetes permissions are missing, please check your RBAC configuration: %v", err )
}
cfg . KubernetesCanPatch = canPatch
s , err := kc . GetSecret ( ctx , cfg . KubeSecret )
if err != nil && kubeclient . IsNotFoundErr ( err ) && ! canCreate {
return fmt . Errorf ( "Tailscale state Secret %s does not exist and we don't have permissions to create it. " +
"If you intend to store tailscale state elsewhere than a Kubernetes Secret, " +
"you can explicitly set TS_KUBE_SECRET env var to an empty string. " +
"Else ensure that RBAC is set up that allows the service account associated with this installation to create Secrets." , cfg . KubeSecret )
} else if err != nil && ! kubeclient . IsNotFoundErr ( err ) {
return fmt . Errorf ( "Getting Tailscale state Secret %s: %v" , cfg . KubeSecret , err )
}
if err != nil {
if ! kubeclient . IsNotFoundErr ( err ) {
return fmt . Errorf ( "getting Tailscale state Secret %s: %v" , cfg . KubeSecret , err )
}
if cfg . AuthKey == "" && ! isOneStepConfig ( cfg ) {
if s == nil {
log . Print ( "TS_AUTHKEY not provided and kube secret does not exist, login will be interactive if needed." )
return nil
if ! canCreate {
return fmt . Errorf ( "tailscale state Secret %s does not exist and we don't have permissions to create it. " +
"If you intend to store tailscale state elsewhere than a Kubernetes Secret, " +
"you can explicitly set TS_KUBE_SECRET env var to an empty string. " +
"Else ensure that RBAC is set up that allows the service account associated with this installation to create Secrets." , cfg . KubeSecret )
}
keyBytes , _ := s . Data [ "authkey" ]
key := string ( keyBytes )
}
// Return early if we already have an auth key.
if cfg . AuthKey != "" || isOneStepConfig ( cfg ) {
return nil
}
if key != "" {
// This behavior of pulling authkeys from kube secrets was added
// at the same time as the patch permission, so we can enforce
// that we must be able to patch out the authkey after
// authenticating if you want to use this feature. This avoids
// us having to deal with the case where we might leave behind
// an unnecessary reusable authkey in a secret, like a rake in
// the grass.
if ! cfg . KubernetesCanPatch {
return errors . New ( "authkey found in TS_KUBE_SECRET, but the pod doesn't have patch permissions on the secret to manage the authkey." )
}
cfg . AuthKey = key
} else {
log . Print ( "No authkey found in kube secret and TS_AUTHKEY not provided, login will be interactive if needed." )
if s == nil {
log . Print ( "TS_AUTHKEY not provided and state Secret does not exist, login will be interactive if needed." )
return nil
}
keyBytes , _ := s . Data [ "authkey" ]
key := string ( keyBytes )
if key != "" {
// Enforce that we must be able to patch out the authkey after
// authenticating if you want to use this feature. This avoids
// us having to deal with the case where we might leave behind
// an unnecessary reusable authkey in a secret, like a rake in
// the grass.
if ! cfg . KubernetesCanPatch {
return errors . New ( "authkey found in TS_KUBE_SECRET, but the pod doesn't have patch permissions on the Secret to manage the authkey." )
}
cfg . AuthKey = key
}
log . Print ( "No authkey found in state Secret and TS_AUTHKEY not provided, login will be interactive if needed." )
return nil
}