I have a Jenkins pipeline (using the File Parameter plugin) that accepts a security token from a user (the token expires after 8 hours). The problem is that if you click on the build number the parameters are shown and the token can then be downloaded by any user:
Is there a way to hide these parameters?
parameters {
base64File 'mytoken'
}
Related
We have many dozens of build pipelines and we want to pause and resume (re-enable) build pipelines from a simple webapp interface as we are making config changes frequently. Here is the MS doc explaining this API:
https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/update%20build?view=azure-devops-rest-5.0#definitionqueuestatus
From this documentation, it appears I need to hit the REST API and change/toggle the DefinitionQueueStatus -- however, this documentation only shows a sample for a build specific operation, whereas I want to pause then re-enable the entire build pipeline. What is the proper way to make this call?
I'm using fetch - and I've tried many dozen formats in the call - the 'ourorg' and 'ourproject' are correct (we use this call structure for many other calls), but all fails for this call below. I grabbed the 'definitionID' from the URL I can visibly see when in the Azure devops portal on the specific build pipeline page, and I'm using it for the {buildID} as I don't know what else to put there. Any guidance to help here is appreciated - I don't need to use fetch btw - any working sample will help here:
fetch(https://dev.azure.com/our_org/our_projectname/_apis/build/builds/definitionId=1593?retry=true&api-version=5.0 {
method: 'PATCH ',
credentials: 'same-origin',
body: 'DefinitionQueueStatus: "Enabled"'
}).then(function(response) {
console.log(response);
})
It seems that the body is incorrect in your post. Here is sample about how to use POSTMAN to access Azure DevOps Services REST APIs.
Generate the PAT, and then record the token, it is important to use to authorization, please see this document.
Create a new request in POSTMAN, it is recommended to put the request in a collection for Azure DevOps Services REST API;
Select the authorization as Basic Auth, you can input the username as any value, and the password as the token which is generated in step1.
Basic Auth
Set the REST API which you want to use,and select the request method type(GET,POST,FETCH ....), here you use https://dev.azure.com/{organization}/{project}/_apis/build/builds/{buildId}?api-version=5.0.
In the Body tab, you can set the request body as raw in json format, and input the value as following:
{
"buildNumber":"#20190607.2",
"buildNumberRevision":1,
"definition":
{
"id":1,
"createdDate":null,
"queueStatus":"paused"
}
}
Everthing is ready now, you can send the request, if sccuess, you will get the response from the REST API.
In your post, the body content is incorrect, the Request Body should meet the format in the REST API document. The DefinitionQueueStatus is a type in definitions. In addition, if you send the request with parameter retry, you will get the message The request body must be empty when the retry parameter is specified..
Using Serenity-Cucumber, I am trying to build a test suite so that I can reuse the step definitions (Given, When, Then, And..) through out multiple feature files.
For example:
Scenario: User Logs in
Given User is on the Login page
When User Logs in using 'userName' and 'password'
Then User on page containing: '/logedin/url/path'
The above test case logs in a user and I will need to use it for other Scenarios. For example, if I add a test case to update a password, the above Scenario will need to be performed before the update password scenario.
The test will need to perform the Login steps and then update password steps. From my limited knowledge, it seems like I will need to have this in the Background: step. So before my update password scenario I will have the following:
Background: User Logs in
Given User is on the Login page
When User Logs in using 'userName' and 'password'
Then User on page containing: '/logedin/url/path'
Scenario: User Updates Password
Given User is on the Manage Account page
When User clicks Update Password
And User type 'existingPassowrd' and 'newPassword'
And User clicks Update Password
Then Password is displayed as 'newPassword'
This gives me an error cucumber.runtime.DuplicateStepDefinitionException which I understand, but I keep reading that serenity-cucumber gives the the option to reuse steps, which again, I get and is a good idea.
So, How do I reuse scenarios or a scenarios' step definitions in other tests? I don't need a new method for them, I just need to call the existing method that I created in the previous scenario.
Is there a way to do this?
Can I do something like this? (or do i not even need to write out the background?)
#Steps
User user;
//This is the background in the feature file.
//Instead of creating methods, I would just reference the pre-existing ones from the other test case.
#Given("^User is on the Login page$")
#When("^User Logs in using '(.*)' and '(.*)'$")
#Then("^User on page containing: '(.*)'$")
//This is the Scenario in the feature file
#Given("^User is on the Manage Account page$")
public void user_is_on_the_manage_account_page(String expectedUrl) throws Exception {
user.is_on_page(expectedUrl);
}
#When("^User clicks Update Password$")
public void user_clicks_update_password() throws Exception {
user.click_update_password();
}
code continues
...
...
...
Found the answer...
As long as the feature file text:
Given User is on the Login page
is written the same in multiple feature files, you only need to write the "step definition" method once
#Given("^User is on the Login page$")
public void user_is_on_the_login_page() throws Exception {
user.is_on_login_page();
}
"User is on the login page" can keep getting re-written on multiple feature files, it will always use that same method user_is_on_the_login_page() and no code needs to be written on that test's step definition file.
I implemented two factor authentication but by following this tutorial
https://learn.microsoft.com/en-us/aspnet/identity/overview/features-api/two-factor-authentication-using-sms-and-email-with-aspnet-identity
I want to make the code expire after single use.
Right now, user receives the same code during the expiration time (which is set to 5 minutes) completes. Is there a way to make the code single use? I couldn't find anything on this subject.
There is a note in the tutorial that you linked to that says:
The 2FA codes are generated using Time-based One-time Password Algorithm and codes are valid for six minutes. If you take more than six minutes to enter the code, you'll get an Invalid code error message.
So, using this method, you cannot make the code expire after user.
You could, as an addition, keep a store of codes that have been used and check against that store before validating the code. You could allow the codes to expire out of that store after 6 minutes, which is their natural expiry time, but in the meantime use them to reject a second authentication.
Alternatively, you can choose to avoid the TOTP method and generate a random code that you store against your user before you send the SMS or email. Then you can check against that code when the user authenticates with it and delete or invalidate the code at that point. Using TOTP means that you could extend this 2FA to use an authenticator app based flow for the authentication too, which is more secure than SMS or email.
AspNetIdentity does not automatically invalidate used second factor codes, a code is always valid for a six minute window, but there is a workaround for this.
One of the inputs to the token generator is the SecurityStamp, which is stored as part of the user account. Token providers that extend the TotpSecurityStampBasedTokenProvider, like for example the EmailTokenProvider, will use the security stamp when they generate and validate a second factor code.
Thus, you can invalidate all issued tokens by changing the security stamp by calling UserManager.UpdateSecurityStampAsync(userId) after a successful two factor authentication.
There is a side effect that may not be desirable, being that other sessions will get logged out when the security stamp changes.
In the ApplicationSignInManager class, you can override TwoFactorSignInAsync and make the call there:
(Note: This is taken from AspNetIdentity, if you are using a different package, make sure to take TwoFactorSignInAsync from that instead and modify it accordingly.)
public override async Task<SignInStatus> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberBrowser)
{
var userId = await GetVerifiedUserIdAsync().WithCurrentCulture();
if (userId == null)
{
return SignInStatus.Failure;
}
var user = await UserManager.FindByIdAsync(userId).WithCurrentCulture();
if (user == null)
{
return SignInStatus.Failure;
}
if (await UserManager.IsLockedOutAsync(user.Id).WithCurrentCulture())
{
return SignInStatus.LockedOut;
}
if (await UserManager.VerifyTwoFactorTokenAsync(user.Id, provider, code).WithCurrentCulture())
{
// When token is verified correctly, clear the access failed count used for lockout
await UserManager.ResetAccessFailedCountAsync(user.Id).WithCurrentCulture();
// Update the security stamp in order to invalidate all issued two factor tokens.
await UserManager.UpdateSecurityStampAsync(user.Id);
await SignInAsync(user, isPersistent, rememberBrowser).WithCurrentCulture();
return SignInStatus.Success;
}
// If the token is incorrect, record the failure which also may cause the user to be locked out
await UserManager.AccessFailedAsync(user.Id).WithCurrentCulture();
return SignInStatus.Failure;
}
If you want only the latest issued code to be valid, you should make the call to UpdateSecurityStampAsync also before any new code is generated.
Right now, in gmail appscript we don't have any option to add a password type field.
Gmail Card Service for add-on has a very good ability to show any thing in it. We can integrate with any app which has basic REST api. We need authentication for that which commonly need password type field.
Any work around to show password type field?
As of now, there is no support for password field in Gmail add-on.
But we can build a hack for it. I hope password is needed only in registration forms. So, we can build a registration form using HTML and that can be served through authorization action.
CardService.newAuthorizationAction().setAuthorizationUrl(loginUrl)
Here, host registration HTML in a web server and pass this URL as "loginUrl" in the above snippet. We have to supply AuthorizationAction for the signup/register button. So, when the user clicks on this button, a new popup page is launched, the user will give the username, password, etc... onsubmit, we can encode all the form data and pass it to the parent Gmail add-on by redirecting it to a script redirection URL which you can generate an add-on. Once the redirection to the script URL comes, there will be a callback in our add-on code from there you can get the form fields which were encoded from registration HTML page.
function generateNewStateToken(callbackName, payload) {
return ScriptApp.newStateToken()
.withMethod(callbackName)
.withArgument("payload", JSON.stringify(payload))
.withTimeout(3600)
.createToken();
}
function getRedirectURI() {
return "https://script.google.com/macros/d/" + ScriptApp.getScriptId() + "/usercallback";
}
var state = generateNewStateToken("registerCallback", {"signup": true});
var reg_url = <reg_url> + "?redirect_uri=" + getRedirectURI() + "&state=" + state;
function registerCallback(cbResp) {
// to access payload which passed in state token: cbResp.parameter.payload;
// in the html serialize all the form fields or data which you want to pass to plugin as query params like: <redirect_uri>?form_data=<encoded_data>&state=<state>
//Note: here the registration HTML page should parse the URL to get the state & redirect_uri from URL.
// to access form_data: cbResp.parameter.form_data
}
I hope this will help you. This is how we are doing the signup/signin flow now.
Looks like you are authorizing a non google service . Please refer to Authorizing custom google services .
I need help for creating the REST endpoints. There are couple of activities :
To change the email there are 3 URL requests required:
/changeemail : Here one time password (OTP) is sent to the user's mobile
/users/email : the user sends the one time password from previous step and system sends the email to the new user to click on the email activate link
/activateemail : user clicks on the link in the new email inbox and server updates the new email
To change password :
/users/password (PATCH) : user submits old password and new password and system accordingly updates the new password
Similarly, there are other endpoints to change profile (field include bday, firstname and last name)
after reading online I believe my system as only users as the resource --> so to update the attributes I was thinking of using a single PATCH for change email and change password and along with that something like operation field so the above two features will look like :
For changing email :
operation : 'sendOTPForEmailChange'
operation : 'sendEmailActivationLink'
operation : 'activateEmail'
For changing password :
operation : 'changePassword'
and I will have only one endpoint for all the above operations that is (in nodejs) :
app.patch('/users', function (req, res) {
// depending upon the operation I delegate it to the respective method
if (req.body.operation === 'sendOTPForEmailChange') {
callMethodA();
} else if (req.body.operation === 'sendEmailActivationLink') {
callMethodB();
} else if (req.body.operation === 'activateEmail') {
callMethodC();
} else if (req.body.operation === 'changePassword') {
callMethodC();
} else sendReplyError();
});
Does this sound a good idea ? If not, someone can help me form the endpoints for changeemail and changepassword.
Answer :
I finally settled for using PATCH with operation field in the HTTP Request Body to indicate what operation has to be performed.
Since I was only modifying a single field of the resource I used the PATCH method.
Also, I wanted to avoid using Verbs in the URI so using 'operation' field looked better.
Some references I used in making this decision :
Wilts answer link here
Mark Nottingham' blog link article
and finally JSON MERGE PATCH link RFC
You should make the links that define the particular resource, avoid using PATCH and adding all the logic in one link keep things simple and use separation of concern in the API
like this
1- /users/otp with HTTP Verb: GET -> to get OTP for any perpose
2- /users/password/otp with HTTP Verb: POST -> to verify OTP for password and sending link via email
3- /users/activate with HTTP Verb: POST to activate the user
4- /users/password with HTTP Verb: PUT to update users password
Hashing Security is a must read, IMHO, should you ever want to implement your own user account system.
Two-factor identification should always be considered, at least as an opt-in feature. How would you integrate it into your login scheme ?
What about identity federation ? Can your user leverage their social accounts to use your app ?
A quick look at Google yielded this and this, as well as this.
Unless you have an excellent reason to do it yourself, I'd spend time integrating a solution that is backed by a strong community for the utility aspects of the project, and focus my time on implementing the business value for your customers.
NB: my text was too long for the comments
Mostly agree with Ghulam's reply, separation of concerns is key. I suggest slightly different endpoints as following:
1. POST /users/otp -> as we are creating a new OTP which should be returned with 200 response.
2. POST /users/email -> to link new email, request to include OTP for verification.
3. PUT /users/email -> to activate the email.
4. PUT /users/password -> to update users password.