-
Notifications
You must be signed in to change notification settings - Fork 124
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
Add ability to send hostname for TLS SNI extension #2432
Conversation
9dcd1e1
to
9e2c83e
Compare
2a1dd5a
to
8ca930c
Compare
ci/authn-k8s/dev/utils.sh
Outdated
if [ -z "$OPENSHIFT_TOKEN" ]; then | ||
oc login $url --username=$OPENSHIFT_USERNAME --password=$OPENSHIFT_PASSWORD --insecure-skip-tls-verify=true | ||
else | ||
oc login $url --token=$OPENSHIFT_TOKEN --insecure-skip-tls-verify=true |
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.
Double quote to prevent globbing and word splitting.
ci/authn-k8s/dev/utils.sh
Outdated
if [ -z "$OPENSHIFT_TOKEN" ]; then | ||
oc login $url --username=$OPENSHIFT_USERNAME --password=$OPENSHIFT_PASSWORD --insecure-skip-tls-verify=true | ||
else | ||
oc login $url --token=$OPENSHIFT_TOKEN --insecure-skip-tls-verify=true |
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.
Double quote to prevent globbing and word splitting.
ci/authn-k8s/dev/utils.sh
Outdated
fi | ||
|
||
if [ -z "$OPENSHIFT_TOKEN" ]; then | ||
oc login $url --username=$OPENSHIFT_USERNAME --password=$OPENSHIFT_PASSWORD --insecure-skip-tls-verify=true |
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.
Double quote to prevent globbing and word splitting.
ci/authn-k8s/dev/utils.sh
Outdated
fi | ||
|
||
if [ -z "$OPENSHIFT_TOKEN" ]; then | ||
oc login $url --username=$OPENSHIFT_USERNAME --password=$OPENSHIFT_PASSWORD --insecure-skip-tls-verify=true |
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.
Double quote to prevent globbing and word splitting.
ci/authn-k8s/dev/utils.sh
Outdated
fi | ||
|
||
if [ -z "$OPENSHIFT_TOKEN" ]; then | ||
oc login $url --username=$OPENSHIFT_USERNAME --password=$OPENSHIFT_PASSWORD --insecure-skip-tls-verify=true |
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.
Double quote to prevent globbing and word splitting.
@@ -25,6 +25,13 @@ def initialize(webservice = nil) | |||
@cert_store = OpenSSL::X509::Store.new | |||
@cert_store.set_default_paths | |||
::Conjur::CertUtils.add_chained_cert(@cert_store, ca_cert) | |||
|
|||
# allows us to add additional CA certs for things like SNI certs | |||
if ENV['SSL_CERT_DIRECTORY'] and File.exists?(ENV['SSL_CERT_DIRECTORY']) and File.exists?(ENV['SSL_CERT_DIRECTORY'] + '/ca') |
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.
To resolve the Code Climate errors (and to make it easier to test), what do you think about refactoring this to something like:
return unless ENV.key?('SSL_CERT_DIRECTORY')
load_additional_certs(
ssl_cert_directory: ENV['SSL_CERT_DIRECTORY'],
cert_store: @cert_store,
cert_utils: ::Conjur::CertUtils
)
We can then break the work into a method like:
def load_additional_certs(ssl_cert_directory:, cert_store:, cert_utils:)
certificate_directory = "#{ssl_cert_directory}/ca"
if Dir.exist?(certificate_directory)
Dir.entries(certificate_directory).each do |file_name|
if File.exist?(file_name)
cert_utils.add_chained_cert(cert_store, File.read(file_name))
else
# Log error message a particular file is missing
end
end
else
# Log error message that the environment variable SSL_CERT_DIRECTORY is missing
end
end
8ca930c
to
824b73f
Compare
ci/authn-k8s/dev/utils.sh
Outdated
if [ -z "$OPENSHIFT_TOKEN" ]; then | ||
oc login $url --username="$OPENSHIFT_USERNAME" --password="$OPENSHIFT_PASSWORD" --insecure-skip-tls-verify=true | ||
else | ||
oc login $url --token="$OPENSHIFT_TOKEN" --insecure-skip-tls-verify=true |
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.
Double quote to prevent globbing and word splitting.
ci/authn-k8s/dev/utils.sh
Outdated
url=$OPENSHIFT_URL | ||
|
||
if [ -z "$OPENSHIFT_TOKEN" ]; then | ||
oc login $url --username="$OPENSHIFT_USERNAME" --password="$OPENSHIFT_PASSWORD" --insecure-skip-tls-verify=true |
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.
Double quote to prevent globbing and word splitting.
ci/authn-k8s/test_oc_entrypoint.sh
Outdated
filename=$1 | ||
api_server_ip=$2 | ||
api_fqdn=$3 | ||
sed -e "s#{{ CONJUR_AUTHN_K8S_TAG }}#$CONJUR_AUTHN_K8S_TAG#g" dev/$filename.${TEMPLATE_TAG}yaml | |
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.
Double quote to prevent globbing and word splitting.
ci/authn-k8s/test_oc_entrypoint.sh
Outdated
filename=$1 | ||
api_server_ip=$2 | ||
api_fqdn=$3 | ||
sed -e "s#{{ CONJUR_AUTHN_K8S_TAG }}#$CONJUR_AUTHN_K8S_TAG#g" dev/$filename.${TEMPLATE_TAG}yaml | |
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.
Double quote to prevent globbing and word splitting.
# printLogs | ||
|
||
conjur_pod=$(retrieve_pod conjur-authn-k8s) | ||
api_server_ip=$(kubectl exec "$conjur_pod" -- sh -c 'echo $KUBERNETES_SERVICE_HOST') |
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.
Expressions don't expand in single quotes, use double quotes for that.
824b73f
to
70e1ec7
Compare
sni_cert=$1 | ||
|
||
if [[ ! -z "$sni_cert" ]]; then | ||
sni_cert="$(realpath $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.
Double quote to prevent globbing and word splitting.
@@ -183,6 +187,7 @@ def k8s_clients | |||
KubeClientFactory.client( | |||
api: 'apis/apps.openshift.io', version: 'v1', host_url: api_url, | |||
options: options | |||
|
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.
Empty line detected around arguments.
- Download and install the RedHat Code Ready Container | ||
- This contains all the necessary pieces to have a local version of | ||
Openshift | ||
- After install, copy down the kubeadmin username/password and update the |
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.
Inconsistent indentation for list items at the same level
- `OPENSHIFT_USERNAME` - username of an account that can create | ||
namespaces, adjust cluster properties, etc | ||
- `OPENSHIFT_PASSWORD` - password of the account | ||
- `OPENSHIFT_URL` - the URL of the RedHat CRC cluster |
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.
Inconsistent indentation for list items at the same level
namespaces, adjust cluster properties, etc | ||
- `OPENSHIFT_PASSWORD` - password of the account | ||
- `OPENSHIFT_URL` - the URL of the RedHat CRC cluster | ||
- If running this locally - use `https://host.docker.internal:6443` so |
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.
Inconsistent indentation for list items at the same level
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 work should have had a security review meeting before any changes were made. I have concerns about pulling in any cert in a directory. We'll need to meet to talk through some threat modeling. @foxefj-cyber - please book some time for us to talk through this.
@andytinkham, I know you're just making sure we're not accidentally introducing a security concern with this:
Although it may have been helpful to have you in a meeting before @foxefj-cyber did any work, in reality, you'd need to be involved in most enhancement/bug fix conversation, which doesn't feel like the best use of your time. I do think certificate related work would certainly benefit from your insight (and seems to be the majority of our security related issues). Moving forward, what do you think about flagging all work that touches certificates as requiring early security architect collaboration? @andytinkham, instead of pulling all certificates from a folder, what do you think about specifying a comma (or other separator) delineated list of certificates? It would allow support for multiple certificate chains while ensuring only the specified certs were loaded. Thoughts? |
For new features, we should be doing security review & threat modeling discussions by default all the time with the occasional path to exception being determining we don't need one (as opposed to the occasional path being to do it). For bug fixes, I'd say if it touches certificates, TLS, encryption, authentication, authorization, or direct handling of secrets values, let's have at least a quick chat at the beginning - we can determine if more is needed after that chat. My guess is most of the time that will be sufficient.
Maybe. @foxefj-cyber & I will talk tomorrow. I'm still at the level of "Should I have concerns here?" not "I definitely have concerns here". Once I get more background, I can weigh in on this idea. Definitely seems worth talking about risks & tradeoffs between the 2 methods. Thanks! |
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.
@foxefj-cyber @micahlee @jvanderhoof & I talked through things and I agree there is no further security issue here. Good to go from a security standpoint.
1bf4838
to
b7fe347
Compare
b7fe347
to
ea71bc9
Compare
a91588d
to
8c9bdc4
Compare
then | ||
docker rm temp_container || true | ||
docker create --name temp_container "$image" | ||
docker cp sni.crt "temp_container:/opt/conjur/etc/ssl/ca/${sni_cert##*/}" |
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.
sni_cert is referenced but not assigned.
-servername "$SNI_FQDN" > sni.out < /dev/null | ||
|
||
docker run --rm -i \ | ||
-w /home -v $PWD:/home \ |
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.
Double quote to prevent globbing and word splitting.
if [[ ! -z $SNI_FQDN ]] | ||
then | ||
docker run --rm -i \ | ||
-w /home -v $PWD:/home \ |
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.
Double quote to prevent globbing and word splitting.
|
||
CONJUR_AUTHN_K8S_TAG=$(echo $CONJUR_AUTHN_K8S_TAG | sed "s/$OPENSHIFT_REGISTRY_URL/$OPENSHIFT_INTERNAL_REGISTRY_URL/") | ||
CONJUR_TEST_AUTHN_K8S_TAG=$(echo $CONJUR_TEST_AUTHN_K8S_TAG | sed "s/$OPENSHIFT_REGISTRY_URL/$OPENSHIFT_INTERNAL_REGISTRY_URL/") | ||
NGINX_TAG=$(echo $NGINX_TAG | sed "s/$OPENSHIFT_REGISTRY_URL/$OPENSHIFT_INTERNAL_REGISTRY_URL/") |
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.
Double quote to prevent globbing and word splitting.
|
||
CONJUR_AUTHN_K8S_TAG=$(echo $CONJUR_AUTHN_K8S_TAG | sed "s/$OPENSHIFT_REGISTRY_URL/$OPENSHIFT_INTERNAL_REGISTRY_URL/") | ||
CONJUR_TEST_AUTHN_K8S_TAG=$(echo $CONJUR_TEST_AUTHN_K8S_TAG | sed "s/$OPENSHIFT_REGISTRY_URL/$OPENSHIFT_INTERNAL_REGISTRY_URL/") | ||
NGINX_TAG=$(echo $NGINX_TAG | sed "s/$OPENSHIFT_REGISTRY_URL/$OPENSHIFT_INTERNAL_REGISTRY_URL/") |
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.
See if you can use ${variable//search/replace} instead.
590e96d
to
ef11b52
Compare
## [1.17.1] - 2022-02-09 | ||
|
||
### Added | ||
- Added support for SNI certificates when talking to the Kubernetes API |
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.
Trailing spaces
## [1.17.1] - 2022-02-09 | ||
|
||
### Added | ||
- Added support for SNI certificates when talking to the Kubernetes API |
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.
Lists should be surrounded by blank lines
The secrets file used for summons needs to contain the following environment | ||
variables | ||
|
||
- openshift |
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.
Inconsistent indentation for list items at the same level
variables | ||
|
||
- openshift | ||
- `OPENSHIFT_USERNAME` - username of an account that can create |
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.
Inconsistent indentation for list items at the same level
- openshift | ||
- `OPENSHIFT_USERNAME` - username of an account that can create | ||
namespaces, adjust cluster properties, etc | ||
- `OPENSHIFT_PASSWORD` - password of the account |
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.
Inconsistent indentation for list items at the same level
Code Climate has analyzed commit ef11b52 and detected 51 issues on this pull request. Here's the issue category breakdown:
The test coverage on the diff in this pull request is 63.6% (50% is the threshold). This pull request will bring the total coverage in the repository to 87.9% (-3.2% change). View more on Code Climate. |
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.
Hey @foxefj-cyber. This feedback is a bit late but I wanted to make sure it was covered at some point.
return unless ENV.key?('SSL_CERT_DIRECTORY') | ||
|
||
load_additional_certs(ENV['SSL_CERT_DIRECTORY']) |
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 might be missing something but is the singular call to add_chained_cert
above not enough ? Wouldn't all the certs be stored in the Conjur variable or the cert file on disk when running inside a pod ?
Separately, I'm wondering about the documentation around the envvar SSL_CERT_DIRECTORY
, I'm not familiar with it yet I see it being used in a few repos and without looking at the code here I wouldn't immediately know how it is used... and I'm not sure if its meaning in the context of the code here is shared across the different places it is used.
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 directory is added in the Dockerfile under the conjur directory and I added pulling in the additional certs so we can add in the CA cert or the self signed cert for the SNI stuff.
if ssl_version != 'SSLv23' | ||
@socket.hostname = options[:hostname] || uri.host | ||
end | ||
@socket.connect | ||
@socket.post_connection_check(@socket.hostname) if @socket.hostname |
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 would like to understand this better, since it's a bit more involved than my simple implementation of always setting the hostname.
- Why are we only excluding this version ? Is it the case that SNI is only expected to be relevant on
ssl_version > SSLv23
? - Can you explain the logic around the
post_connection_check
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.
SNI is an extension in TLS only so we don't want to bother adding the hostname if they are using SSLv23 for some reason.
the post_connection_check will throw an error if we expected a certain SNI certificate but we didn't get it - this makes sure that if we are expecting SNI we get the proper certificate
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.
On board with (1). For (2) I was sure I was able to get errors thrown with just calls to #connect
, I'll reconfirm.
@sni_fails | ||
Scenario: Authenticate as a Pod. | ||
When I authenticate with authn-k8s as "pod/inventory-pod" without cert and key | ||
Then the HTTP status is "401" | ||
|
||
@sni_success | ||
Scenario: Authenticate as a Pod. | ||
Given I can login to pod matching "app=inventory-pod" to authn-k8s as "*/*" | ||
Then I can authenticate pod matching "pod/inventory-pod" with authn-k8s as "*/*" |
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 the unit tests provide amazing validation and coverage for supporting SNI. I'm curious why we are adding a cucumber test which to me seems to be testing the same thing as the unit tests but paying a significantly higher price i.e. deploying a whole Conjur master for each one of these tests ?
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.
these are just to validate that the entire solution works with SNI - purely for validation.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
The Kubernetes API endpoint can include a path, as is the case with the Rancher API, the websocket implementation should take the URL as is instead of taking only host and port. The commit originally included support for server name indication (SNI) on the the websocket client, which enables the client to be specific about the host it is trying to reach in the first step of the TLS handshake, preventing common name mismatch errors. However, that commit was removed in favour of the more comprehensive work to support SNI at #2432.
Desired Outcome
Ability to define the SNI certificate hostname so the proper certificate is returned from the Kubernetes API Server.
Implemented Changes
Describe how the desired outcome above has been achieved with this PR. In
particular, consider:
Added change to send the hostname during SSL connection as well as adding testing.
Connected Issue/Story
CyberArk internal issue link: ONYX-14386
Definition of Done
At least 1 todo must be completed in the sections below for the PR to be
merged.
Changelog
CHANGELOG update
Test coverage
changes, or
Documentation
README
s) were updated in this PRBehavior
Security