-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify server certificate and known hosts management #1807
Simplify server certificate and known hosts management #1807
Conversation
…4-simplify-known-hosts-mgmt
Also, supply a little more repository info during List(), so that the CLI can display them.
This moves repository validation from the client to server before creating it. It also introduces new --insecure-skip-server-validation flag, which shall deprecate --insecure-ignore-host-key in the future. This new switch shall also reflect that HTTPS certificate validation can be skipped now.
This PR is work in progress. I have yet to write tests and polish the change. And since the change is quite substantial, I want to know your thoughts on the general direction this is going. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I explicitly chose not to use a subPath mount for this ConfigMap since with subPath, changes to the ConfigMap do not get propagated to the pods automatically (i.e. you have to restart pods for changes to become effective). Using a non-subPath mount, the pods can pick up the change instantly once the ConfigMap has been propagated across the cluster.
looks like you're making good progress - let us know if you need any help |
So is this PR basically munging both the disabling of (a) TLS host certificate verification and (b) SSH host key verification into a single option I think I'm on-board with this change, however, I think the flag should be named |
@jessesuen Yes, correct, I think it would be best to provide a single option for both cases. I am with you that I'm also in the process to extend the API to provide some kind of rudimentary certificate and known hosts management, so that we can attach host keys or TLS information to repository FQDNs. I'm a little unsure where this would belong, I see two possibilities:
I think the first would make more sense, since certs/known hosts are valid for multiple repositories, when served from same server. Third possibilities is one I didn't see yet, but maybe someone else has an idea? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to request changes. It wasn't clear to me when reviewing what insecure
flags. It appears to combine both flags into one uber flag.
How we deal with SSH and HTTPS is usually quite independent in the code, and we know even experienced users find it confusing what flags to use.
What are the options about having a separate flag named similarly to kubectl
? E.g. --insecure-skip-tls-verify
?
I also wonder, how should we document updating the list of known hosts?
cmd/argocd/commands/repo.go
Outdated
for _, r := range repos.Items { | ||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", r.Repo, r.Username, r.ConnectionState.Status, r.ConnectionState.Message) | ||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", r.Repo, strconv.FormatBool((r.InsecureIgnoreHostKey || r.Insecure)), r.Username, r.ConnectionState.Status, r.ConnectionState.Message) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor - you can use %v
server/repository/repository.proto
Outdated
// RepoAccessResponse is the response to RepoAccessQuery | ||
message RepoAccessResponse { | ||
// Whether access is possible | ||
bool accessPossible = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these returned? I can't find mention elsewhere in the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Supposed to be used with the next commits - I think it's better to have a dedicated response rather than to display the raw error to the user, even if it'll contain basically the same message later on.
util/git/client.go
Outdated
// explicitly replace it with default client for repositories without the | ||
// insecure flag set. | ||
if IsHTTPSURL(rawRepoURL) { | ||
if insecure { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we always use this library? it's got to work, so lets just always use it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, it's basically the counterpart to IsSSHURL() - but as of know, just a wrapper around a regexp's MatchString(), and not thoroughly tested yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I was clear, I'd like to avoid the if/else here on line 79. I think you can always use the customHttpClient
?
Oh - I know I've given a lot of feedback on this, but I think you're doing a splendid job on a tricky problem. |
Your feedback is much appreciated! |
This requires some more work than expected. So, apologies, I'm working on a good fix for native Git client supporting custom CA bundle. |
…4-simplify-known-hosts-mgmt
…4-simplify-known-hosts-mgmt
Found a good solution that works perfectly and is not dirty by using PR now feature complete and hopefully bug-free. Ready for another review or merge, as you see fit. |
Great, I'm glad you found Thank you for completing it @jannfis ! |
I think Kustomize remote bases are not covered by the feature-set in this PR, @alexmt - I had a quick look at the code implementing Kustomize in |
@@ -16,6 +17,9 @@ p, role:admin, applications, update, */*, allow | |||
p, role:admin, applications, delete, */*, allow | |||
p, role:admin, applications, sync, */*, allow | |||
p, role:admin, applications, override, */*, allow | |||
p, role:admin, certificates, create, *, allow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good
} | ||
}, | ||
} | ||
command.Flags().BoolVar(&removeAllCerts, "remove-all", false, "Remove all configured certificates of all types from server (DANGER: use with care!)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nuke all, I feel like I would never want to have the risk of using this. Also, I initially thought this, incorrectly, this was remove all the certificates for the REPOSERVER - could there be a risk others think the same. How much do we need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was convenient during test cycles, but you are right, it's quite a dangerous option (therefore the fat DANGER sign). However, the same could be accomplished by using a *
wildcard as the repo server name, which is not even really documented.
I see two options:
- Ask the user with a prompt if he really wants to perform that dangerous operation when
--remove-all
is specified or*
was given as the repo-server name without any other selector such as--cert-type
- Discard both possibilities for good, and have the user delete data from ConfigMap objects if they really want to get rid of all certificates.
Thinking of it, sh*t happens too often and I guess variant 2 is the better one. Will remove the code from the CLI. Do you think we should check on server side as well, whether '*' was specified in case someone writes against the API?
Example for adding a HTTPS repository to ArgoCD without verifying the server's certificate (**Caution:** This is **not** recommended for production use): | ||
|
||
```bash | ||
argocd repo add --insecure-repository https://git.example.com/test-repo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the name of this flag, it's not the repository that is insecure, it is that we do not check the security of the connection. Hmmmmmm....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the CLI, it still is --insecure-skip-server-verification
. But I guess there is still some disagreement on the name of the switch. --insecure
is already occupied for the connection between CLI and ArgoCD server component.
But personally I think, when the connection to the repository is insecure, the repository itself should be considered insecure as well - just for the fact that you don't know if ArgoCD is really connecting to the right repo, and not a MITM-installed one. If the flag is --insecure-repository
, it should be clear to not trust that repository. And to not use it for production purposes.
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceCertificates, rbacpolicy.ActionGet, ""); err != nil { | ||
return nil, err | ||
} | ||
certList, err := s.db.ListRepoCertificates(ctx, &db.CertificateListSelector{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor - you could just return certList, err
here (same below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Will fix.
|
||
service CertificateService { | ||
// List all available certificates | ||
rpc List(RepositoryCertificateQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.RepositoryCertificateList) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. You need to rename these as they'll get weird swagger operation IDs (something like Mixin5
).
I recommend "verb+nou"n names so you get sensible REST IDs.
E.g.
rpc ListCertificates(RepositoryCertificateQuery)
rpc CreateCertificate(RepositoryCertificateCreateRequest)
rpc DeleteCertificate(RepositoryCertificateQuery)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that is the reason for the swagger going wild. Thanks for the clarification, will rename those methods to the names you proposed, they sound clear & concise to me.
|
||
certificateList := make([]string, 0) | ||
|
||
// TODO: Implement maximum amount of data to parse |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's still something that I have to do but deemed not important enough for now. I guess the maximum POST size is already limited by gRPC anyway.
@@ -37,6 +37,13 @@ type ArgoDB interface { | |||
|
|||
// ListHelmRepoURLs lists configured helm repositories | |||
ListHelmRepos(ctx context.Context) ([]*appv1.HelmRepository, error) | |||
|
|||
// ListRepoCerticifates lists all configured certificates | |||
ListRepoCertificates(ctx context.Context, selector *CertificateListSelector) (*appv1.RepositoryCertificateList, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, I don't feel strongly about it
PasswordSecret *apiv1.SecretKeySelector `json:"passwordSecret,omitempty"` | ||
SSHPrivateKeySecret *apiv1.SecretKeySelector `json:"sshPrivateKeySecret,omitempty"` | ||
InsecureIgnoreHostKey bool `json:"insecureIgnoreHostKey,omitempty"` | ||
// The URL to the repository |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good stuff
// Returns the ConfigMap with the given name from the cluster. | ||
// The ConfigMap must be labeled with "app.kubernetes.io/part-of: argocd" in | ||
// order to be retrievable. | ||
func (mgr *SettingsManager) GetNamedConfigMap(configMapName string) (*apiv1.ConfigMap, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor - all config map are named - aren't they - how about GetConfigMapByName
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better, clear & concise. Will rename it, thanks!
|
||
If you are connecting a repository on a HTTPS server using a self-signed certificate, or a certificate signed by a custom Certificate Authority (CA) which are not known to ArgoCD, the repository will not be added due to security reasons. This is indicated by an error message such as `x509: certificate signed by unknown authority`. | ||
|
||
1. You can let ArgoCD connect the repository in an insecure way, without verifying the server's certificate at all. This can be accomplished by using the `--insecure-repository` flag when adding the repository with the `argocd` CLI utility. However, this should be done only for non-production setups, as it imposes a serious security issue through possible man-in-the-middle attacks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is incorrect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unsure about what you mean. What exactly is incorrect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @alexec means it supposed to be insecure-ignore-host-key
instead of --insecure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conditional approval - Alex M will be following up.
Trying to implement e2e tests for it |
This change addresses some of the remaining minor changes that were requested during development/review cycles of argoproj#1807: - Rename GetNamedConfigMap() to GetConfigMapByName() - Rename CRUD methods of CertificateService to something more sensible, so that swagger doesn't get confused. - Get rid of possibly dangerous --remove-all switch in "cert rm" command, and also prevent user from accidentally specifying a single wildcard as repo-server name
…es (#1934) * Make sure insecure flag works for remote Kustomize bases
This PR aims to make it more simple to connect SSH and HTTPS repositories to ArgoCD. It addresses #1514 and the following topics:
A management interface for SSH known hosts management has yet to be introduced, as well as an interface for managing HTTPS certificates.