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

HPCC-30160 Automatic SOAPCALL secret credentials #17737

Merged

Conversation

afishbeck
Copy link
Member

@afishbeck afishbeck commented Sep 1, 2023

Type of change:

  • This change is a bug fix (non-breaking change which fixes an issue).
  • This change is a new feature (non-breaking change which adds functionality).
  • This change improves the code (refactor or other change that does not change the functionality)
  • This change fixes warnings (the fix does not alter the functionality or the generated code)
  • This change is a breaking change (fix or feature that will cause existing behavior to change).
  • This change alters the query API (existing queries will have to be recompiled)

Checklist:

  • My code follows the code style of this project.
    • My code does not create any new warnings from compiler, build system, or lint.
  • The commit message is properly formatted and free of typos.
    • The commit message title makes sense in a changelog, by itself.
    • The commit is signed.
  • My change requires a change to the documentation.
    • I have updated the documentation accordingly, or...
    • I have created a JIRA ticket to update the documentation.
    • Any new interfaces or exported functions are appropriately commented.
  • I have read the CONTRIBUTORS document.
  • The change has been fully tested:
    • I have added tests to cover my changes.
    • All new and existing tests passed.
    • I have checked that this change does not introduce memory leaks.
    • I have used Valgrind or similar tools to check for potential issues.
  • I have given due consideration to all of the following potential concerns:
    • Scalability
    • Performance
    • Security
    • Thread-safety
    • Cloud-compatibility
    • Premature optimization
    • Existing deployed queries will not be broken
    • This change fixes the problem, not just the symptom
    • The target branch of this pull request is appropriate for such a change.
  • There are no similar instances of the same problem that should be addressed
    • I have addressed them here
    • I have raised JIRA issues to address them separately
  • This is a user interface / front-end modification
    • I have tested my changes in multiple modern browsers
    • The component(s) render as expected

Smoketest:

  • Send notifications about my Pull Request position in Smoketest queue.
  • Test my draft Pull Request.

Testing:

@github-actions
Copy link

github-actions bot commented Sep 1, 2023

@afishbeck
Copy link
Member Author

afishbeck commented Sep 1, 2023

@ghalliday this is a draft of how automatic replacement of URLs with secrets might work.

Basically, starting with some ECL using a URL:

ds := HTTPCALL('http://localhost:8010/WsWorkunits/WUQuery.json', 'GET', 'application/json', OutRec1);
OUTPUT(ds);

  1. Enable configuration for automatic URL to secret mapping either in values.yaml or environment.conf:
mapSoapCallUrlsToSecrets=true
warnIfUrlNotMappedToSecret=true

  1. Calculate the needed secret name via command line tool:
> ecl url-secret-name https://user:pw@localhost:8010/WsWorkunits/WUQuery.json
http-connect-ssl-localhost-8010-3065364863

Note: I think having some parts readable will help operations be able to manage. But credentials, path, and parameters should not be visible due to possible exposure of sensitive information.

  1. Create a secret with that name in vault or kubernetes (under ecl category):
http-connect-ssl-localhost-8010-3065364863
{
  "url": "http://localhost:8880/roxie/abc?123",
  "username": "aaa",
  "password": "bbb"
 }

  1. Publish and run the query, which should now go to the desination in the secret using that username and pw.

Copy link
Member

@ghalliday ghalliday left a comment

Choose a reason for hiding this comment

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

@afishbeck this looks really good. A few comments, many of which should be ignored for this PR.

system/jlib/jsecrets.cpp Show resolved Hide resolved
hashvalue = hashcz((const unsigned char *)userPasswordPair, hashvalue);
}
if (hashvalue)
secretName.append('-').append(hashvalue);
Copy link
Member

Choose a reason for hiding this comment

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

would the following be better than decimal?

appendf("-%08x", hashvalue)

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree hex would be better, but I may leave off the leading 0's unless you think it would be beneficial in some way.

CriticalBlock block(persistentCrit);
if (!persistentInitDone)
CriticalBlock block(globalFeatureCrit);
if (!globalFeaturesInitDone)
Copy link
Member

Choose a reason for hiding this comment

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

See https://github.com/hpcc-systems/HPCC-Platform/pull/17715/files for an alternative way of coding this that also allows the values to be updated when the configuration changes. You may want to adopt something similar, but may be better as a separate PR since this looks very close to ready

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes that would be a good follow on PR

int maxPersistentRequests = conf->getPropInt("@maxHttpCallPersistentRequests", 0);
#endif
int maxPersistentRequests = 0;
if (isContainerized())
Copy link
Member

Choose a reason for hiding this comment

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

I think better to always use the containerized code, and have the configuration in the esp config.

Copy link
Member Author

@afishbeck afishbeck Sep 5, 2023

Choose a reason for hiding this comment

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

@ghalliday I'm not sure how best to make that work. But if we were going to do it for bare-metal now is the time otherwise the way it's configured would change over time.
The process this is running in wouldn't be esp, it would be roxie, or eclagent, or thor. I don't think when those are running on bare-metal they have a common way of getting at their config? I could be wrong but in a simple test I didn't see the componentConfig getting set.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok much better. It's now using the component config in both cloud and bare-metal.

if (!secret)
{
if (required)
throw MakeStringException(0, "%sCALL %s SECRET not found", wscType == STsoap ? "SOAP" : "HTTP", secretName);
Copy link
Member

Choose a reason for hiding this comment

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

trivial/unrelated.

static const char * queryCallName(WSCType wscType) { return wscType == STsoap ? "SOAPCALL" : "HTTPCALL"; }
would clean the code up.

Copy link
Member Author

Choose a reason for hiding this comment

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

went ahead and cleaned this up while I was in there.

url.getDynamicUrlSecretName(secretName);
if (secretName.length())
{
if (loadConnectSecret(nullptr, secretName, tempArray, issuer, proxyAddress, false, wscType))
Copy link
Member

Choose a reason for hiding this comment

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

Add an option to require all soapcalls use secrets (and pass true)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@ghalliday ghalliday marked this pull request as ready for review September 15, 2023 14:51
@ghalliday
Copy link
Member

@afishbeck I think Jake will probably want to implement his changes for https://track.hpccsystems.com/browse/HPCC-30259 on top of this, so worth finishing it and getting it merged. Is there anything I can do to help?

@afishbeck
Copy link
Member Author

@ghalliday updated, please review.

Copy link
Member

@ghalliday ghalliday left a comment

Choose a reason for hiding this comment

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

A couple of comments, but looks like it is very close to ready.

@@ -885,21 +884,21 @@ bool loadConnectSecret(const char *vaultId, const char *secretName, UrlArray &ur
if (!secret)
{
if (required)
throw MakeStringException(0, "%sCALL %s SECRET not found", wscType == STsoap ? "SOAP" : "HTTP", secretName);
throw MakeStringException(0, "%sCALL %s SECRET not found", getWsCallTypeName(wscType), secretName);
Copy link
Member

Choose a reason for hiding this comment

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

%sCALL will now become %s

@afishbeck
Copy link
Member Author

@ghalliday updated json schema and log/exception text.

Copy link
Member

@ghalliday ghalliday left a comment

Choose a reason for hiding this comment

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

@afishbeck looks good, please squash

@ghalliday ghalliday changed the base branch from master to candidate-9.4.x September 21, 2023 16:14
@afishbeck
Copy link
Member Author

afishbeck commented Sep 21, 2023

@ghalliday squashed and resolved conflicts.

Signed-off-by: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
@ghalliday ghalliday merged commit 71bc409 into hpcc-systems:candidate-9.4.x Sep 22, 2023
47 of 50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants