User gets "Not authorized to perform action: Invalid key" when making a create request with cURL.
Creating and updating Rally artifacts with command-line cURL requires that the user maintain a session with a cookie. Otherwise a GET request when a user gets a security token and a POST request when a user hits the create or update endpoint happen in the context of two separate HTTP sessions. By the time the second request is issued, the key acquired during the first request is expired, hence "Not authorized to perform action: Invalid key" error.
A cURL scenario in which a cookie is used to maintain the session is described below. This post predates the released a new feature, API Key, which removed the need to explicitly request the token and append it to POST requests. API Key is different from the security token.
*******BEGIN cURL scenario********
An Authorization key is valid for as long as the HTTP session is valid. The difference between the browser REST client and your command-line curl is that the browser is automatically maintaining the HTTP session via a session cookie. Without session cookies, each curl request constitutes a new HTTP session.
You can tell curl to store a session cookie in order to persist the HTTP session. Here's how:
$ curl -u "user@example.com:topsecret" https://rally1.rallydev.com/slm/webservice/v2.0/security/authorize -c cookie.txt
Response:
{ "OperationResult" : { "Errors" : [ ],
"SecurityToken" : "<A new Security Token - to be used below>",
"Warnings" : [ ],
"_rallyAPIMajor" : "2",
"_rallyAPIMinor" : "0"
} }
Note the session ID information in the cookie:
$ more cookie.txt
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_rally1.rallydev.com FALSE / TRUE 0 JSESSIONID <JSessionID>
#HttpOnly_.rally1.rallydev.com TRUE / TRUE 0 ZSESSIONID <ZSessionID aka API Key>
#HttpOnly_.rally1.rallydev.com TRUE / TRUE 0 SUBBUCKETID <SubBucketID>
Finally, issue the create command with curl, using the token you obtained via the authorize endpoint, and the -b
flag for curl to specify the cookie file:
$ curl -u 'user@example.com:topsecret' -H "Content-Type: application/json" -d '{"HierarchicalRequirement": {"Name": "mystory"}}' https://rally1.rallydev.com/slm/webservice/v2.0/HierarchicalRequirement/create?key=<Session Key from above> -b cookie.txt
Response:
{ "CreateResult" : { "Errors" : [ ],
"Object" : {
"CreationDate" : "2013-07-06T15:00:32.380Z",
"LastUpdateDate" : "2013-07-06T15:00:32.437Z",
"Name" : "mystory",
"ObjectID" : <Your ObjectID>,
"Project" : { "_rallyAPIMajor" : "2",
"_rallyAPIMinor" : "0",
"_ref" : "https://rally1.rallydev.com/slm/webservice/v2.0/project/<Project ObjectID>",
"_refObjectName" : "My Project",
"_type" : "Project"
},
"Rank" : 10433947185.0,
"Subscription" : { "_rallyAPIMajor" : "2",
"_rallyAPIMinor" : "0",
"_ref" : "https://rally1.rallydev.com/slm/webservice/v2.0/subscription/<Subscription ObjectID>",
"_refObjectName" : "My Subscription",
"_type" : "Subscription"
},
"Workspace" : { "_rallyAPIMajor" : "2",
"_rallyAPIMinor" : "0",
"_ref" : "https://rally1.rallydev.com/slm/webservice/v2.0/workspace/<WorkspaceObjectID>",
"_refObjectName" : "My Workspace",
"_type" : "Workspace"
},
"_CreatedAt" : "just now",
},
"Warnings" : [ ],
"_rallyAPIMajor" : "2",
"_rallyAPIMinor" : "0"
} }
*******END cURL scenario********
1. Generate an API Key from Rally Application Manager page
There is a link to Rally Application Manager available from the help page that introduces this feature.
Follow this link, login with your Rally credentials, and generate the key
This API key can be used in the zsessionid header of a cURL command.
2. POST request
In the terminal issue a command that follows this syntax. Replace _myKeY123 with the valid API Key:
curl --header "zsessionid:_myKeY123" -H "Content-Type: application/json" -d"{\"Defect\":{\"Name\":\"bad defect\"}}" https://rally1.rallydev.com/slm/webservice/v2.0/Defect/create
Note that when using API Key it is no longer necessary to explicitly pass user credentials.