github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/utils/keypaths/keypaths.go (about)

     1  /*
     2  Copyright 2021 Gravitational, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package keypaths defines several keypaths used by multiple Teleport services.
    18  package keypaths
    19  
    20  import (
    21  	"fmt"
    22  	"path/filepath"
    23  	"strings"
    24  )
    25  
    26  // keypath constants aren't exported in order to force
    27  // helper function usage and maintain consistency.
    28  const (
    29  	// sessionKeyDir is a sub-directory where session keys are stored
    30  	sessionKeyDir = "keys"
    31  	// sshDirSuffix is the suffix of a sub-directory where SSH certificates are stored.
    32  	sshDirSuffix = "-ssh"
    33  	// fileNameKnownHosts is a file where known hosts are stored.
    34  	fileNameKnownHosts = "known_hosts"
    35  	// fileExtTLSCert is the suffix/extension of a file where a TLS cert is stored.
    36  	fileExtTLSCert = "-x509.pem"
    37  	// fileNameTLSCerts is a file where TLS Cert Authorities are stored.
    38  	fileNameTLSCerts = "certs.pem"
    39  	// fileExtCert is the suffix/extension of a file where an SSH Cert is stored.
    40  	fileExtSSHCert = "-cert.pub"
    41  	// fileExtPPK is the suffix/extension of a file where an SSH keypair is stored in PuTTY PPK format.
    42  	fileExtPPK = ".ppk"
    43  	// fileExtPub is the extension of a file where a public key is stored.
    44  	fileExtPub = ".pub"
    45  	// fileExtLocalCA is the extension of a file where a self-signed localhost CA cert is stored.
    46  	fileExtLocalCA = "-localca.pem"
    47  	// appDirSuffix is the suffix of a sub-directory where app TLS certs are stored.
    48  	appDirSuffix = "-app"
    49  	// db DirSuffix is the suffix of a sub-directory where db TLS certs are stored.
    50  	dbDirSuffix = "-db"
    51  	// kubeDirSuffix is the suffix of a sub-directory where kube TLS certs are stored.
    52  	kubeDirSuffix = "-kube"
    53  	// kubeConfigSuffix is the suffix of a kubeconfig file stored under the keys directory.
    54  	kubeConfigSuffix = "-kubeconfig"
    55  	// fileNameKubeCredLock is file name of lockfile used to prevent excessive login attempts.
    56  	fileNameKubeCredLock = "kube_credentials.lock"
    57  	// casDir is the directory name for where clusters certs are stored.
    58  	casDir = "cas"
    59  	// fileExtPem is the extension of a file where a public certificate is stored.
    60  	fileExtPem = ".pem"
    61  	// currentProfileFileName is a file containing the name of the current profile
    62  	currentProfileFilename = "current-profile"
    63  	// profileFileExt is the suffix of a profile file.
    64  	profileFileExt = ".yaml"
    65  	// oracleWalletDirSuffix is the suffix of the oracle wallet database directory.
    66  	oracleWalletDirSuffix = "-wallet"
    67  )
    68  
    69  // Here's the file layout of all these keypaths.
    70  // ~/.tsh/							   --> default base directory
    71  // ├── current-profile                 --> file containing the name of the currently active profile
    72  // ├── one.example.com.yaml            --> file containing profile details for proxy "one.example.com"
    73  // ├── two.example.com.yaml            --> file containing profile details for proxy "two.example.com"
    74  // ├── known_hosts                     --> trusted certificate authorities (their keys) in a format similar to known_hosts
    75  // └── keys							   --> session keys directory
    76  //    ├── one.example.com              --> Proxy hostname
    77  //    │   ├── certs.pem                --> TLS CA certs for the Teleport CA
    78  //    │   ├── foo                      --> Private Key for user "foo"
    79  //    │   ├── foo.pub                  --> Public Key
    80  //    │   ├── foo.ppk                  --> PuTTY PPK-formatted keypair for user "foo"
    81  //    │   ├── kube_credentials.lock    --> Kube credential lockfile, used to prevent excessive relogin attempts
    82  //    │   ├── foo-x509.pem             --> TLS client certificate for Auth Server
    83  //    │   ├── foo-ssh                  --> SSH certs for user "foo"
    84  //    │   │   ├── root-cert.pub        --> SSH cert for Teleport cluster "root"
    85  //    │   │   └── leaf-cert.pub        --> SSH cert for Teleport cluster "leaf"
    86  //    │   ├── foo-app                  --> App access certs for user "foo"
    87  //    │   │   ├── root                 --> App access certs for cluster "root"
    88  //    │   │   │   ├── appA-x509.pem    --> TLS cert for app service "appA"
    89  //    │   │   │   └── appB-x509.pem    --> TLS cert for app service "appB"
    90  //    │   │   │   └── appB-localca.pem --> Self-signed localhost CA cert for app service "appB"
    91  //    │   │   └── leaf                 --> App access certs for cluster "leaf"
    92  //    │   │       └── appC-x509.pem    --> TLS cert for app service "appC"
    93  //    │   ├── foo-db                   --> Database access certs for user "foo"
    94  //    │   │   ├── root                 --> Database access certs for cluster "root"
    95  //    │   │   │   ├── dbA-x509.pem     --> TLS cert for database service "dbA"
    96  //    │   │   │   ├── dbB-x509.pem     --> TLS cert for database service "dbB"
    97  //    │   │   │   └── dbC-wallet       --> Oracle Client wallet Configuration directory.
    98  //    │   │   ├── leaf                 --> Database access certs for cluster "leaf"
    99  //    │   │   │   └── dbC-x509.pem     --> TLS cert for database service "dbC"
   100  //    │   │   └── proxy-localca.pem    --> Self-signed TLS Routing local proxy CA
   101  //    │   ├── foo-kube                 --> Kubernetes certs for user "foo"
   102  //    │   |    ├── root                 --> Kubernetes certs for Teleport cluster "root"
   103  //    │   |    │   ├── kubeA-kubeconfig --> standalone kubeconfig for Kubernetes cluster "kubeA"
   104  //    │   |    │   ├── kubeA-x509.pem   --> TLS cert for Kubernetes cluster "kubeA"
   105  //    │   |    │   ├── kubeB-kubeconfig --> standalone kubeconfig for Kubernetes cluster "kubeB"
   106  //    │   |    │   ├── kubeB-x509.pem   --> TLS cert for Kubernetes cluster "kubeB"
   107  //    │   |    │   └── localca.pem      --> Self-signed localhost CA cert for Teleport cluster "root"
   108  //    │   |    └── leaf                 --> Kubernetes certs for Teleport cluster "leaf"
   109  //    │   |        ├── kubeC-kubeconfig --> standalone kubeconfig for Kubernetes cluster "kubeC"
   110  //    │   |        └── kubeC-x509.pem   --> TLS cert for Kubernetes cluster "kubeC"
   111  //    |   └── cas                       --> Trusted clusters certificates
   112  //    |        ├── root.pem             --> TLS CA for teleport cluster "root"
   113  //    |        ├── leaf1.pem            --> TLS CA for teleport cluster "leaf1"
   114  //    |        └── leaf2.pem            --> TLS CA for teleport cluster "leaf2"
   115  //    └── two.example.com			    --> Additional proxy host entries follow the same format
   116  //		  ...
   117  
   118  // KeyDir returns the path to the keys directory.
   119  //
   120  // <baseDir>/keys
   121  func KeyDir(baseDir string) string {
   122  	return filepath.Join(baseDir, sessionKeyDir)
   123  }
   124  
   125  // CurrentProfile returns the path to the current profile file.
   126  //
   127  // <baseDir>/current-profile
   128  func CurrentProfileFilePath(baseDir string) string {
   129  	return filepath.Join(baseDir, currentProfileFilename)
   130  }
   131  
   132  // ProfileFilePath returns the path to the profile file for the given profile.
   133  //
   134  // <baseDir>/<profileName>.yaml
   135  func ProfileFilePath(baseDir, profileName string) string {
   136  	return filepath.Join(baseDir, profileName+profileFileExt)
   137  }
   138  
   139  // KnownHostsPath returns the path to the known hosts file.
   140  //
   141  // <baseDir>/known_hosts
   142  func KnownHostsPath(baseDir string) string {
   143  	return filepath.Join(baseDir, fileNameKnownHosts)
   144  }
   145  
   146  // ProxyKeyDir returns the path to the proxy's keys directory.
   147  //
   148  // <baseDir>/keys/<proxy>
   149  func ProxyKeyDir(baseDir, proxy string) string {
   150  	return filepath.Join(KeyDir(baseDir), proxy)
   151  }
   152  
   153  // UserKeyPath returns the path to the users's private key
   154  // for the given proxy.
   155  //
   156  // <baseDir>/keys/<proxy>/<username>.
   157  func UserKeyPath(baseDir, proxy, username string) string {
   158  	return filepath.Join(ProxyKeyDir(baseDir, proxy), username)
   159  }
   160  
   161  // TLSCertPath returns the path to the users's TLS certificate
   162  // for the given proxy.
   163  //
   164  // <baseDir>/keys/<proxy>/<username>-x509.pem
   165  func TLSCertPath(baseDir, proxy, username string) string {
   166  	return filepath.Join(ProxyKeyDir(baseDir, proxy), username+fileExtTLSCert)
   167  }
   168  
   169  // PublicKeyPath returns the path to the users's public key
   170  // for the given proxy.
   171  //
   172  // <baseDir>/keys/<proxy>/<username>.pub
   173  func PublicKeyPath(baseDir, proxy, username string) string {
   174  	return filepath.Join(ProxyKeyDir(baseDir, proxy), username+fileExtPub)
   175  }
   176  
   177  // CAsDir returns path to trusted clusters certificates directory.
   178  //
   179  // <baseDir>/keys/<proxy>/cas
   180  func CAsDir(baseDir, proxy string) string {
   181  	return filepath.Join(ProxyKeyDir(baseDir, proxy), casDir)
   182  }
   183  
   184  // TLSCAsPath returns the path to the users's TLS CA's certificates
   185  // for the given proxy.
   186  // <baseDir>/keys/<proxy>/certs.pem
   187  // DELETE IN 10.0. Deprecated
   188  func TLSCAsPath(baseDir, proxy string) string {
   189  	return filepath.Join(ProxyKeyDir(baseDir, proxy), fileNameTLSCerts)
   190  }
   191  
   192  // TLSCAsPathCluster returns the path to the specified cluster's CA directory.
   193  //
   194  // <baseDir>/keys/<proxy>/cas/<cluster>.pem
   195  func TLSCAsPathCluster(baseDir, proxy, cluster string) string {
   196  	return filepath.Join(ProxyKeyDir(baseDir, proxy), casDir, cluster+fileExtPem)
   197  }
   198  
   199  // SSHDir returns the path to the user's SSH directory for the given proxy.
   200  //
   201  // <baseDir>/keys/<proxy>/<username>-ssh
   202  func SSHDir(baseDir, proxy, username string) string {
   203  	return filepath.Join(ProxyKeyDir(baseDir, proxy), username+sshDirSuffix)
   204  }
   205  
   206  // PPKFilePath returns the path to the user's PuTTY PPK-formatted keypair
   207  // for the given proxy and cluster.
   208  //
   209  // <baseDir>/keys/<proxy>/<username>.ppk
   210  func PPKFilePath(baseDir, proxy, username string) string {
   211  	return filepath.Join(ProxyKeyDir(baseDir, proxy), username+fileExtPPK)
   212  }
   213  
   214  // SSHCertPath returns the path to the users's SSH certificate
   215  // for the given proxy and cluster.
   216  //
   217  // <baseDir>/keys/<proxy>/<username>-ssh/<cluster>-cert.pub
   218  func SSHCertPath(baseDir, proxy, username, cluster string) string {
   219  	return filepath.Join(SSHDir(baseDir, proxy, username), cluster+fileExtSSHCert)
   220  }
   221  
   222  // AppDir returns the path to the user's app directory
   223  // for the given proxy.
   224  //
   225  // <baseDir>/keys/<proxy>/<username>-app
   226  func AppDir(baseDir, proxy, username string) string {
   227  	return filepath.Join(ProxyKeyDir(baseDir, proxy), username+appDirSuffix)
   228  }
   229  
   230  // AppCertDir returns the path to the user's app cert directory
   231  // for the given proxy and cluster.
   232  //
   233  // <baseDir>/keys/<proxy>/<username>-app/<cluster>
   234  func AppCertDir(baseDir, proxy, username, cluster string) string {
   235  	return filepath.Join(AppDir(baseDir, proxy, username), cluster)
   236  }
   237  
   238  // AppCertPath returns the path to the user's TLS certificate
   239  // for the given proxy, cluster, and app.
   240  //
   241  // <baseDir>/keys/<proxy>/<username>-app/<cluster>/<appname>-x509.pem
   242  func AppCertPath(baseDir, proxy, username, cluster, appname string) string {
   243  	return filepath.Join(AppCertDir(baseDir, proxy, username, cluster), appname+fileExtTLSCert)
   244  }
   245  
   246  // AppLocalCAPath returns the path to a self-signed localhost CA for the given
   247  // proxy, cluster, and app.
   248  //
   249  // <baseDir>/keys/<proxy>/<username>-app/<cluster>/<appname>-localca.pem
   250  func AppLocalCAPath(baseDir, proxy, username, cluster, appname string) string {
   251  	return filepath.Join(AppCertDir(baseDir, proxy, username, cluster), appname+fileExtLocalCA)
   252  }
   253  
   254  // DatabaseDir returns the path to the user's database directory
   255  // for the given proxy.
   256  //
   257  // <baseDir>/keys/<proxy>/<username>-db
   258  func DatabaseDir(baseDir, proxy, username string) string {
   259  	return filepath.Join(ProxyKeyDir(baseDir, proxy), username+dbDirSuffix)
   260  }
   261  
   262  // DatabaseCertDir returns the path to the user's database cert directory
   263  // for the given proxy and cluster.
   264  //
   265  // <baseDir>/keys/<proxy>/<username>-db/<cluster>
   266  func DatabaseCertDir(baseDir, proxy, username, cluster string) string {
   267  	return filepath.Join(DatabaseDir(baseDir, proxy, username), cluster)
   268  }
   269  
   270  // DatabaseCertPath returns the path to the user's TLS certificate
   271  // for the given proxy, cluster, and database.
   272  //
   273  // <baseDir>/keys/<proxy>/<username>-db/<cluster>/<dbname>-x509.pem
   274  func DatabaseCertPath(baseDir, proxy, username, cluster, dbname string) string {
   275  	return filepath.Join(DatabaseCertDir(baseDir, proxy, username, cluster), dbname+fileExtTLSCert)
   276  }
   277  
   278  // DatabaseOracleWalletDirectory returns the path to the user's Oracle Wallet configuration directory.
   279  // for the given proxy, cluster and database.
   280  // <baseDir>/keys/<proxy>/<username>-db/<cluster>/dbname-wallet/
   281  func DatabaseOracleWalletDirectory(baseDir, proxy, username, cluster, dbname string) string {
   282  	return filepath.Join(DatabaseCertDir(baseDir, proxy, username, cluster), dbname+oracleWalletDirSuffix)
   283  }
   284  
   285  // KubeDir returns the path to the user's kube directory
   286  // for the given proxy.
   287  //
   288  // <baseDir>/keys/<proxy>/<username>-kube
   289  func KubeDir(baseDir, proxy, username string) string {
   290  	return filepath.Join(ProxyKeyDir(baseDir, proxy), username+kubeDirSuffix)
   291  }
   292  
   293  // KubeCertDir returns the path to the user's kube cert directory
   294  // for the given proxy and cluster.
   295  //
   296  // <baseDir>/keys/<proxy>/<username>-kube/<cluster>
   297  func KubeCertDir(baseDir, proxy, username, cluster string) string {
   298  	return filepath.Join(KubeDir(baseDir, proxy, username), cluster)
   299  }
   300  
   301  // KubeCertPath returns the path to the user's TLS certificate
   302  // for the given proxy, cluster, and kube cluster.
   303  //
   304  // <baseDir>/keys/<proxy>/<username>-kube/<cluster>/<kubename>-x509.pem
   305  func KubeCertPath(baseDir, proxy, username, cluster, kubename string) string {
   306  	return filepath.Join(KubeCertDir(baseDir, proxy, username, cluster), kubename+fileExtTLSCert)
   307  }
   308  
   309  // KubeConfigPath returns the path to the user's standalone kubeconfig
   310  // for the given proxy, cluster, and kube cluster.
   311  //
   312  // <baseDir>/keys/<proxy>/<username>-kube/<cluster>/<kubename>-kubeconfig
   313  func KubeConfigPath(baseDir, proxy, username, cluster, kubename string) string {
   314  	return filepath.Join(KubeCertDir(baseDir, proxy, username, cluster), kubename+kubeConfigSuffix)
   315  }
   316  
   317  // KubeCredLockfilePath returns the kube credentials lock file for given proxy
   318  //
   319  // <baseDir>/keys/<proxy>/kube_credentials.lock
   320  func KubeCredLockfilePath(baseDir, proxy string) string {
   321  	return filepath.Join(ProxyKeyDir(baseDir, proxy), fileNameKubeCredLock)
   322  }
   323  
   324  // IsProfileKubeConfigPath makes a best effort attempt to check if the given
   325  // path is a profile specific kubeconfig path generated by this package.
   326  func IsProfileKubeConfigPath(path string) (bool, error) {
   327  	if path == "" {
   328  		return false, nil
   329  	}
   330  	// Split path on sessionKeyDir since we can't do filepath.Match with baseDir
   331  	splitPath := strings.Split(path, "/"+sessionKeyDir+"/")
   332  	match := fmt.Sprintf("*/*%v/*/*%v", kubeDirSuffix, kubeConfigSuffix)
   333  	return filepath.Match(match, splitPath[len(splitPath)-1])
   334  }
   335  
   336  // IdentitySSHCertPath returns the path to the identity file's SSH certificate.
   337  //
   338  // <identity-file-dir>/<path>-cert.pub
   339  func IdentitySSHCertPath(path string) string {
   340  	return path + fileExtSSHCert
   341  }
   342  
   343  // TrimCertPathSuffix returns the given path with any cert suffix/extension trimmed off.
   344  func TrimCertPathSuffix(path string) string {
   345  	trimmedPath := strings.TrimSuffix(path, fileExtTLSCert)
   346  	trimmedPath = strings.TrimSuffix(trimmedPath, fileExtSSHCert)
   347  	return trimmedPath
   348  }