Skip to content
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

fix(sni) stricter detection and handling of duplicate snis #2285

Merged
merged 3 commits into from
Apr 3, 2017

Conversation

p0pr0ck5
Copy link
Contributor

@p0pr0ck5 p0pr0ck5 commented Mar 29, 2017

Previously, if a duplicate sni was detected as part of the 'snis'
sugar param, we still created the certificate object, as well as
any previously non-existant sni encountered before the conflicting
element. This commit prevents creation of orphan entries by checking
for the existence all posted snis before creating the certificate
and sni objects.

This commit also cleans up the naming schemes for admin API certificate
routes integration tests (no functional change).

Fixes issue #2275, among other behavioral inconsistencies.

@Tieske
Copy link
Member

Tieske commented Mar 30, 2017

if some of this is based on the unique constraint as mentioned in #2275 then there should also be a migration adding that constraint to the postgres schema. No?

@p0pr0ck5
Copy link
Contributor Author

Err. The name field is a PRIMARY KEY in postgres. Does this not make it unique?

@p0pr0ck5
Copy link
Contributor Author

p0pr0ck5 commented Mar 30, 2017

if some of this is based on the unique constraint as mentioned in #2275 then there should also be a migration adding that constraint to the postgres schema. No?

Just clarifying, the point there was that the constraint is not applied to cassandra.

btw, this PR also fixes a few other misbehaviors, like creating certs and some SNI objects even when a PK violation is detected (yet still returning a 409).

@Tieske
Copy link
Member

Tieske commented Mar 30, 2017

Just clarifying, the point there was that the constraint is not applied to cassandra.

then we need to add a schema change then. Right?

@p0pr0ck5
Copy link
Contributor Author

From what I can tell, the behavior seen is #2275 is a result of this PK definition for the cassandra ssl_servers_names table: https://github.com/Mashape/kong/blob/master/kong/dao/migrations/cassandra.lua#L238

Prior to this PR, we always created a new Certificate object, regardless of SNI name duplicates, which means that we never had a PK violation for cassandra when we try to insert the duplicate SNI (indeed, that's one behavior this PR fixes). So it seems the cassandra schema change here under the hood would actually be to alter the PK- which, from what I can tell, is not an option (it would involve copying and duplicating the table with the new PK- this sounds awful ;) ).

It seems that we can handle this ourselves by adding the unique flag to the schema, as discussed @Tieske. Took me a while to wrap my head around this. It does indeed seem a bit odd to add this flag to the primary_key, but given the circumstances, it seems appropriate- It does resolve the buggy behavior, with the detriment of slightly worse (but acceptable) performance on SNI insert (since the cassandra db driver has to mock the constraint behavior).

local seen = {}
if type(snis) == "table" then
for i = 1, #snis do
local sni_name = snis[i]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@p0pr0ck5 btw: why not use ipairs and implictly declare and assign sni_name? any specific reason you avoid that? (just wondering)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ipairs is a bit slower than an iterative loop, due to the function call overhead, but given the likely scope of this, it probably wouldn't make much difference either way :) let me know if this is a blocker (doesnt seem like it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(also the existing code below follows the same pattern; maintaining consistency inside a module is important imo)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for i = 1, #t

-- its fairly inefficient that we have to loop twice over the datastore
-- but no support for OR queries means we gotsta!
local seen = {}
if type(snis) == "table" then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems this check is extraneous here. Following the beginning of this function, I believe snis can either be nil or a table. Hence, if snis then seems simpler and reasonable enough.

local seen = {}
if type(snis) == "table" then
for i = 1, #snis do
local sni_name = snis[i]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for i = 1, #t

-- dont add the certificate or any snis if we have an SNI conflict
-- its fairly inefficient that we have to loop twice over the datastore
-- but no support for OR queries means we gotsta!
local seen = {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this seen table does not have to belong to this scope, but can be scoped under the if snis then block?

@thibaultcha thibaultcha force-pushed the fix/sni-conflict branch 2 times, most recently from 6a92e26 to 6da94a8 Compare April 3, 2017 20:53
@thibaultcha thibaultcha changed the base branch from next to master April 3, 2017 20:53
p0pr0ck5 and others added 2 commits April 3, 2017 13:57
Previously, if a duplicate SNI was detected as part of the 'snis'
sugar param, we still created the certificate object, as well as
any previously non-existant sni encountered before the conflicting
element. This commit prevents creation of orphan entries by checking
for the existence all posted snis before creating the certificate
and sni objects.

This commit also cleans up the naming schemes for admin API certificate
routes integration tests (no functional change).

Signed-off-by: Thibault Charbonnier <thibaultcha@me.com>
* new test to enforce the uniqueness of a SNI by its name
* run `/certificates` and `/snis` tests with both PostgreSQL and
  Cassandra.
@thibaultcha thibaultcha added pr/ready (but hold merge) No more concerns, but do not merge yet (probably a conflict of interest with another PR or release) and removed pr/status/needs review labels Apr 3, 2017
In such cold code paths, we can make the code more readable. Let's also
not call SNIs "sni_name" since "sni" already carries this meaning.
@thibaultcha thibaultcha merged commit 57ad9ff into master Apr 3, 2017
@thibaultcha thibaultcha deleted the fix/sni-conflict branch April 3, 2017 23:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr/ready (but hold merge) No more concerns, but do not merge yet (probably a conflict of interest with another PR or release)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants