@@ -39,17 +39,14 @@ var (
3939type serverConfig struct {
4040 cfg * config.Config
4141 hostKeys []ssh.Signer
42+ hostKeyToCertMap map [string ]* ssh.Certificate
4243 authorizedKeysClient * authorizedkeys.Client
4344}
4445
45- func newServerConfig (cfg * config.Config ) (* serverConfig , error ) {
46- authorizedKeysClient , err := authorizedkeys .NewClient (cfg )
47- if err != nil {
48- return nil , fmt .Errorf ("failed to initialize GitLab client: %w" , err )
49- }
50-
46+ func parseHostKeys (keyFiles []string ) []ssh.Signer {
5147 var hostKeys []ssh.Signer
52- for _ , filename := range cfg .Server .HostKeyFiles {
48+
49+ for _ , filename := range keyFiles {
5350 keyRaw , err := os .ReadFile (filename )
5451 if err != nil {
5552 log .WithError (err ).WithFields (log.Fields {"filename" : filename }).Warn ("Failed to read host key" )
@@ -63,11 +60,70 @@ func newServerConfig(cfg *config.Config) (*serverConfig, error) {
6360
6461 hostKeys = append (hostKeys , key )
6562 }
63+
64+ return hostKeys
65+ }
66+
67+ func parseHostCerts (hostKeys []ssh.Signer , certFiles []string ) map [string ]* ssh.Certificate {
68+ keyToCertMap := map [string ]* ssh.Certificate {}
69+ hostKeyIndex := make (map [string ]int )
70+
71+ for index , hostKey := range hostKeys {
72+ hostKeyIndex [string (hostKey .PublicKey ().Marshal ())] = index
73+ }
74+
75+ for _ , filename := range certFiles {
76+ keyRaw , err := os .ReadFile (filename )
77+ if err != nil {
78+ log .WithError (err ).WithFields (log.Fields {"filename" : filename }).Warn ("failed to read host certificate" )
79+ continue
80+ }
81+ publicKey , _ , _ , _ , err := ssh .ParseAuthorizedKey (keyRaw )
82+ if err != nil {
83+ log .WithError (err ).WithFields (log.Fields {"filename" : filename }).Warn ("failed to parse host certificate" )
84+ continue
85+ }
86+
87+ cert , ok := publicKey .(* ssh.Certificate )
88+ if ! ok {
89+ log .WithFields (log.Fields {"filename" : filename }).Warn ("failed to decode host certificate" )
90+ continue
91+ }
92+
93+ hostRawKey := string (cert .Key .Marshal ())
94+ index , found := hostKeyIndex [hostRawKey ]
95+ if found {
96+ keyToCertMap [hostRawKey ] = cert
97+
98+ certSigner , err := ssh .NewCertSigner (cert , hostKeys [index ])
99+ if err != nil {
100+ log .WithError (err ).WithFields (log.Fields {"filename" : filename }).Warn ("the host certificate doesn't match the host private key" )
101+ continue
102+ }
103+
104+ hostKeys [index ] = certSigner
105+ } else {
106+ log .WithFields (log.Fields {"filename" : filename }).Warnf ("no matching private key for certificate %s" , filename )
107+ }
108+ }
109+
110+ return keyToCertMap
111+ }
112+
113+ func newServerConfig (cfg * config.Config ) (* serverConfig , error ) {
114+ authorizedKeysClient , err := authorizedkeys .NewClient (cfg )
115+ if err != nil {
116+ return nil , fmt .Errorf ("failed to initialize GitLab client: %w" , err )
117+ }
118+
119+ hostKeys := parseHostKeys (cfg .Server .HostKeyFiles )
66120 if len (hostKeys ) == 0 {
67121 return nil , fmt .Errorf ("No host keys could be loaded, aborting" )
68122 }
69123
70- return & serverConfig {cfg : cfg , authorizedKeysClient : authorizedKeysClient , hostKeys : hostKeys }, nil
124+ hostKeyToCertMap := parseHostCerts (hostKeys , cfg .Server .HostCertFiles )
125+
126+ return & serverConfig {cfg : cfg , authorizedKeysClient : authorizedKeysClient , hostKeys : hostKeys , hostKeyToCertMap : hostKeyToCertMap }, nil
71127}
72128
73129func (s * serverConfig ) getAuthKey (ctx context.Context , user string , key ssh.PublicKey ) (* authorizedkeys.Response , error ) {
0 commit comments