feat: allow using a local RSA key for machine keys (#7671)

* Allow using a local RSA key for machine keys

* Add check for key validity

* Fix naming error

* docs: provide translations of invalid key

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Ari
2024-04-23 11:38:07 +02:00
committed by GitHub
parent df50c3835b
commit e46dd121cd
19 changed files with 80 additions and 13 deletions

View File

@@ -774,13 +774,22 @@ func (s *Server) ListMachineKeys(ctx context.Context, req *mgmt_pb.ListMachineKe
func (s *Server) AddMachineKey(ctx context.Context, req *mgmt_pb.AddMachineKeyRequest) (*mgmt_pb.AddMachineKeyResponse, error) {
machineKey := AddMachineKeyRequestToCommand(req, authz.GetCtxData(ctx).OrgID)
// If there is no pubkey supplied, then AddUserMachineKey will generate a new one
pubkeySupplied := len(machineKey.PublicKey) > 0
details, err := s.command.AddUserMachineKey(ctx, machineKey)
if err != nil {
return nil, err
}
keyDetails, err := machineKey.Detail()
if err != nil {
return nil, err
// Return key details only if the pubkey wasn't supplied, otherwise the user already has
// private key locally
var keyDetails []byte
if !pubkeySupplied {
var err error
keyDetails, err = machineKey.Detail()
if err != nil {
return nil, err
}
}
return &mgmt_pb.AddMachineKeyResponse{
KeyId: machineKey.KeyID,

View File

@@ -237,6 +237,7 @@ func AddMachineKeyRequestToCommand(req *mgmt_pb.AddMachineKeyRequest, resourceOw
},
ExpirationDate: expDate,
Type: authn.KeyTypeToDomain(req.Type),
PublicKey: req.PublicKey,
}
}

View File

@@ -5,6 +5,7 @@ import (
"time"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
@@ -78,6 +79,12 @@ func (key *MachineKey) valid() (err error) {
if err := key.content(); err != nil {
return err
}
// If a key is supplied, it should be a valid public key
if len(key.PublicKey) > 0 {
if _, err := crypto.BytesToPublicKey(key.PublicKey); err != nil {
return zerrors.ThrowInvalidArgument(nil, "COMMAND-5F3h1", "Errors.User.Machine.Key.Invalid")
}
}
key.ExpirationDate, err = domain.ValidateExpirationDate(key.ExpirationDate)
return err
}

View File

@@ -18,6 +18,16 @@ import (
"github.com/zitadel/zitadel/internal/zerrors"
)
const fakePubkey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp4qNBuUu/HekF2E5bOtA
oEL76zS0NQdZL3ByEJ3hZplJhE30ITPIOLW3+uaMMM+obl/LLapwG2vdhvutQtx/
FOLJmXysbG3RL9zjXDBT5IE+nGFC7ctsi5FGbHQbAm45E3HHCSk7gfmTy9hxyk1K
GsyU8BDeOWasJO6aeXqpOnRM8vw/fY+6mHVC9CxcIroSfrIabFGe/mP6qpBGeFSn
APymBc/8lca4JaPv2/u/rBhnaAHZiUuCS1+MonWelOb+MSfq48VgtpiaYIVY9szI
esorA6EJ9pO17ROEUpX5wP5Oir+yGJU27jSvLCjvK6fOFX+OwUM9L8047JKoo+Nf
PwIDAQAB
-----END PUBLIC KEY-----`
func TestCommands_AddMachineKey(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
@@ -145,7 +155,7 @@ func TestCommands_AddMachineKey(t *testing.T) {
"key1",
domain.AuthNKeyTypeJSON,
time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC),
[]byte("public"),
[]byte(fakePubkey),
),
),
),
@@ -161,14 +171,14 @@ func TestCommands_AddMachineKey(t *testing.T) {
},
Type: domain.AuthNKeyTypeJSON,
ExpirationDate: time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC),
PublicKey: []byte("public"),
PublicKey: []byte(fakePubkey),
},
},
res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
key: true,
key: false,
},
},
{
@@ -194,7 +204,7 @@ func TestCommands_AddMachineKey(t *testing.T) {
"key1",
domain.AuthNKeyTypeJSON,
time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC),
[]byte("public"),
[]byte(fakePubkey),
),
),
),
@@ -210,14 +220,35 @@ func TestCommands_AddMachineKey(t *testing.T) {
KeyID: "key1",
Type: domain.AuthNKeyTypeJSON,
ExpirationDate: time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC),
PublicKey: []byte("public"),
PublicKey: []byte(fakePubkey),
},
},
res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
key: true,
key: false,
},
},
{
"key added with invalid public key",
fields{
eventstore: eventstoreExpect(t),
},
args{
ctx: context.Background(),
key: &MachineKey{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
ResourceOwner: "org1",
},
KeyID: "key1",
Type: domain.AuthNKeyTypeJSON,
PublicKey: []byte("incorrect"),
},
},
res{
err: zerrors.IsErrorInvalidArgument,
},
},
}
@@ -237,9 +268,8 @@ func TestCommands_AddMachineKey(t *testing.T) {
}
if tt.res.err == nil {
assert.Equal(t, tt.res.want, got)
if tt.res.key {
assert.NotEqual(t, "", tt.args.key.PrivateKey)
}
receivedKey := len(tt.args.key.PrivateKey) > 0
assert.Equal(t, tt.res.key, receivedKey)
}
})
}

View File

@@ -111,6 +111,7 @@ Errors:
Key:
NotFound: Машинният ключ не е намерен
AlreadyExisting: Машинният ключ вече съществува
Invalid: Публичният ключ не е валиден RSA публичен ключ във формат PKIX с PEM кодиране
Secret:
NotExisting: Тайната не съществува
Invalid: Тайната е невалидна

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Klíč stroje nenalezen
AlreadyExisting: Klíč stroje již existuje
Invalid: Veřejný klíč není platný veřejný klíč RSA ve formátu PKIX s kódováním PEM
Secret:
NotExisting: Tajemství neexistuje
Invalid: Tajemství je neplatné

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Maschinen Schlüssel nicht gefunden
AlreadyExisting: Machine Schlüssel exisiert bereits
Invalid: Der öffentliche Schlüssel ist kein gültiger öffentlicher RSA-Schlüssel im PKIX-Format mit PEM-Kodierung
Secret:
NotExisting: Secret existiert nicht
Invalid: Secret ist ungültig

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Machine key not found
AlreadyExisting: Machine key already existing
Invalid: Public key is not a valid RSA public key in PKIX format with PEM encoding
Secret:
NotExisting: Secret doesn't exist
Invalid: Secret is invalid

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Clave de máquina no encontrada
AlreadyExisting: La clave de máquina ya existe
Invalid: La clave pública no es una clave pública RSA válida en formato PKIX con codificación PEM
Secret:
NotExisting: El secreto no existe
Invalid: El secret no es válido

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Clé de la machine non trouvée
AlreadyExisting: Clé de la machine déjà existante
Invalid: La clé publique n'est pas une clé publique RSA valide au format PKIX avec encodage PEM
Secret:
NotExisting: Secret n'existe pas
Invalid: Secret n'est pas valide

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Chiave macchina non trovato
AlreadyExisting: Chiave macchina già esistente
Invalid: La chiave pubblica non è una chiave pubblica RSA valida in formato PKIX con codifica PEM
Secret:
NotExisting: Secret non esiste
Invalid: Secret non è valido

View File

@@ -102,6 +102,7 @@ Errors:
Key:
NotFound: マシーンキーが見つかりません
AlreadyExisting: すでに存在しているマシーンキーです
Invalid: 公開キーは、PEM エンコードを使用した PKIX 形式の有効な RSA 公開キーではありません
Secret:
NotExisting: シークレットは存在しません
Invalid: 無効なシークレットです

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Machine key не е пронајден
AlreadyExisting: Machine key веќе постои
Invalid: Јавниот клуч не е валиден јавен клуч RSA во формат PKIX со PEM кодирање
Secret:
NotExisting: Тајната не постои
Invalid: Тајната е невалидна

View File

@@ -108,6 +108,7 @@ Errors:
Key:
NotFound: Machine sleutel niet gevonden
AlreadyExisting: Machine sleutel al bestaand
Invalid: De openbare sleutel is geen geldige openbare RSA-sleutel in PKIX-indeling met PEM-codering
Secret:
NotExisting: Geheim bestaat niet
Invalid: Geheim is ongeldig

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Klucz maszyny nie znaleziony
AlreadyExisting: Klucz maszyny już istnieje
Invalid: Klucz publiczny nie jest prawidłowym kluczem publicznym RSA w formacie PKIX z kodowaniem PEM
Secret:
NotExisting: Sekret nie istnieje
Invalid: Sekret jest nieprawidłowy

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: Chave de máquina não encontrada
AlreadyExisting: Chave de máquina já existe
Invalid: A chave pública não é uma chave pública RSA válida no formato PKIX com codificação PEM
Secret:
NotExisting: Segredo não existe
Invalid: Segredo é inválido

View File

@@ -110,6 +110,7 @@ Errors:
Key:
NotFound: Машинный ключ не найден
AlreadyExisting: Машинный ключ уже существует
Invalid: Открытый ключ не является допустимым открытым ключом RSA в формате PKIX с кодировкой PEM
Secret:
NotExisting: Ключ не существует
Invalid: Ключ недействителен

View File

@@ -109,6 +109,7 @@ Errors:
Key:
NotFound: 未找到机器密钥
AlreadyExisting: 已有的机器钥匙
Invalid: 公钥不是采用 PEM 编码的 PKIX 格式的有效 RSA 公钥
Secret:
NotExisting: 秘密并不存在
Invalid: 秘密是无效的