mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 01:47:33 +00:00
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:
@@ -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,
|
||||
|
@@ -237,6 +237,7 @@ func AddMachineKeyRequestToCommand(req *mgmt_pb.AddMachineKeyRequest, resourceOw
|
||||
},
|
||||
ExpirationDate: expDate,
|
||||
Type: authn.KeyTypeToDomain(req.Type),
|
||||
PublicKey: req.PublicKey,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@@ -111,6 +111,7 @@ Errors:
|
||||
Key:
|
||||
NotFound: Машинният ключ не е намерен
|
||||
AlreadyExisting: Машинният ключ вече съществува
|
||||
Invalid: Публичният ключ не е валиден RSA публичен ключ във формат PKIX с PEM кодиране
|
||||
Secret:
|
||||
NotExisting: Тайната не съществува
|
||||
Invalid: Тайната е невалидна
|
||||
|
@@ -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é
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -102,6 +102,7 @@ Errors:
|
||||
Key:
|
||||
NotFound: マシーンキーが見つかりません
|
||||
AlreadyExisting: すでに存在しているマシーンキーです
|
||||
Invalid: 公開キーは、PEM エンコードを使用した PKIX 形式の有効な RSA 公開キーではありません
|
||||
Secret:
|
||||
NotExisting: シークレットは存在しません
|
||||
Invalid: 無効なシークレットです
|
||||
|
@@ -109,6 +109,7 @@ Errors:
|
||||
Key:
|
||||
NotFound: Machine key не е пронајден
|
||||
AlreadyExisting: Machine key веќе постои
|
||||
Invalid: Јавниот клуч не е валиден јавен клуч RSA во формат PKIX со PEM кодирање
|
||||
Secret:
|
||||
NotExisting: Тајната не постои
|
||||
Invalid: Тајната е невалидна
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -110,6 +110,7 @@ Errors:
|
||||
Key:
|
||||
NotFound: Машинный ключ не найден
|
||||
AlreadyExisting: Машинный ключ уже существует
|
||||
Invalid: Открытый ключ не является допустимым открытым ключом RSA в формате PKIX с кодировкой PEM
|
||||
Secret:
|
||||
NotExisting: Ключ не существует
|
||||
Invalid: Ключ недействителен
|
||||
|
@@ -109,6 +109,7 @@ Errors:
|
||||
Key:
|
||||
NotFound: 未找到机器密钥
|
||||
AlreadyExisting: 已有的机器钥匙
|
||||
Invalid: 公钥不是采用 PEM 编码的 PKIX 格式的有效 RSA 公钥
|
||||
Secret:
|
||||
NotExisting: 秘密并不存在
|
||||
Invalid: 秘密是无效的
|
||||
|
Reference in New Issue
Block a user