php-opencloud / openstack

PHP SDK for OpenStack clouds
Apache License 2.0
222 stars 152 forks source link

RackSpace OpenStack #316

Open ap-coder opened 3 years ago

ap-coder commented 3 years ago

Any chance someone is working on this?

It would be really helpful in getting it integrated with my app so i was just wondering.

haphan commented 3 years ago

@ap-coder This SDK should work with RackSpace Openstack for the most part. What is the issue you are having?

braisdesousa commented 3 years ago

Hi @haphan ! I'm at the same point than @ap-coder . I'm moving my old ObjectStore from https://github.com/rackspace/php-opencloud to this new OpenStack code ( the old rackspace still requiring deprected code)

Trying to follow with https://php-openstack-sdk.readthedocs.io/en/latest/services/object-store/v1/account.html docs, I create a very simple PHP Code as follows

$openstack = new OpenStack([ 'authUrl' => 'https://identity.api.rackspacecloud.com/v2.0/', 'region' => 'LON', 'user' => [ 'id' => 'myUserName', 'password' => 'myApiKey' ], 'scope' => ['project' => ['id' => 'object-store']] ]); But, the output I got while trying to execute this code is ` HTTP Error

  The remote server returned a "404 Not Found" error for the following transaction:                                                                                                                                                                

  Request                                                                                                                                                                                                                                          

POST /v2.0/auth/tokens HTTP/1.1
User-Agent: GuzzleHttp/7
Content-Type: application/json
Host: identity.api.rackspacecloud.com

{"auth":{"identity":{"password":{"user":{"id":"myUser","password":"myApiKey"}},"methods":["password"]},"scope":{"project":{"id":"object-store"}}}}

Response

  HTTP/1.1 404 Not Found                                                                                                                                                                                                                           
  Date: Wed, 04 Nov 2020 07:15:53 GMT, Wed, 04 Nov 2020 07:15:53 GMT                                                                                                                                                                               
  Content-Type: application/xml                                                                                                                                                                                                                    
  Vary: Accept, Accept-Encoding, X-Auth-Token, Accept-Encoding                                                                                                                                                                                     
  X-NewRelic-App-Data: PxQCWVFVDwQTVVRTBAQAUlATGhE1AwE2QgNWEVlbQFtcC2VOYgRBFAhTQz1JKV1BQwEYQmRBRQ8KVhZkBwRDI0ASVAtbWUBbXAsbTQFPA05XGAJVVVMAdh1QTU8GHRVRB1JUBwMFU1MDU1oHXgAAEB8DWA1CBG4=                                                            
  X-Trans-Id: eyJyZXF1ZXN0SWQiOiJlNzRhMjM0My00NzlhLTQzMzAtODcwZi00Mzk5ODFjYTk3MjgiLCJvcmlnaW4iOm51bGx9                                                                                                                                             
  Content-Length: 1139                                                                                                                                                                                                                             
  Server: Jetty(9.4.z-SNAPSHOT)                                                                                                                                                                                                                    
  Strict-Transport-Security: max-age=15552000; includeSubDomains                                                                                                                                                                                   
  X-XSS-Protection: 1; mode=block                                                                                                                                                                                                                  
  X-Content-Type-Options: nosniff                                                                                                                                                                                                                  
  X-Frame-Options: DENY                                                                                                                                                                                                                            
  Content-Security-Policy: default-src 'self'                                                                                                                                                                                                      

  <?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns17:itemNotFound xmlns:ns2="http://docs.openstack.org/common/api/v1.0" xmlns:ns3="http://docs.openstack.org/compute/api/v1.1" xmlns:ns4="http://www.w3.org/2005/Atom" xmlns:ns5="http://
  tity/api/ext/RAX-AUTH/v1.0" xmlns:ns7="http://docs.rackspace.com/identity/api/ext/RAX-KSKEY/v1.0" xmlns:ns8="http://docs.rackspace.com/identity/api/ext/RAX-KSQA/v1.0" xmlns:ns9="http://docs.openstack.org/identity/api/ext/OS-KSEC2/v1.0" xmlns
  ttp://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0" xmlns:ns12="http://docs.openstack.org/identity/api/ext/OS-KSCATALOG/v1.0" xmlns:ns13="http://docs.rackspace.com/core/event" xmlns:ns14="http://schemas.dmtf.org/cloud/audit/1.0/event" x
  16="http://docs.rackspacecloud.com/auth/api/v1.1" xmlns:ns17="http://fault.common.api.rackspace.com/v1.0"><code>404</code><message>Resource Not Found</message></ns17:itemNotFound>                                                              

  Further information                                                                                                                                                                                                                              

Please ensure that the resource you're trying to access actually exists. Visit http://docs.php-opencloud.com/en/latest/http-codes for more information about debugging HTTP status codes, or file a support issue on https://github.com/php-openc `

I have also opened a ticket with Rackspace, but I thing here I could get a better solution.

haphan commented 3 years ago

@braisdesousa Can you try to use identity v3 instead?

Most likely RackSpace has deprecated v2 identity endpoint.

braisdesousa commented 3 years ago

This may be the problem @haphan, there is not identityV3 on rackspace. All documentation is based on https://developer.rackspace.com/docs/cloud-identity/quickstart/

And just refers to https://lon.identity.api.rackspacecloud.com/v2.0/ to identificate. Using CURL I'm able to retrive the catalog list of services, also my TOKEN to use with X-Auth-Token. And the public URL endpoints of this catalog services,

But I cannot make it work with OpenStack.

haphan commented 3 years ago

@braisdesousa I recall this issue with auth v2.0 now. Pardon me because not many platforms are still using v2.

For v2 identity you'd need to override the config for IdentityService, it is documented here

Can you give it a try and report back? Thanks

braisdesousa commented 3 years ago

Test Done, following that documentation I'm able to create the same Guzzle Post, thant I was doing with CURL. And, this part "works", using it as identityService, is till giving the same response.

$httpClient = new Client([
            'base_uri' => TransportUtils::normalizeUrl('https://lon.identity.api.rackspacecloud.com/v2.0/'),
            'handler'  => HandlerStack::create(),
            'json'=>["auth"=>['RAX-KSKEY:apiKeyCredentials'=>["username"=>"username","apiKey"=>'apikey']]],
            'defaults'=>['headers'  => ['content-type' => 'application/json', 'Accept' => 'application/json']],
            ]
        );
        #I've used this piece just to check getting the same result as with the CURL client identifiing to Rackspace.
        #$response=$httpClient->post("tokens");
        #$body=json_decode($response->getBody()->getContents(),true);

        $options = [
            'authUrl'         => 'https://lon.identity.api.rackspacecloud.com/v2.0/',
            'region'          => 'LON',
            'username'        => 'username',
            'password'        => 'apikey',
            'identityService' => Service::factory($httpClient),
        ];

        /** @var OpenStack $openstack */
        $openstack = new OpenStack($options);

        $containers = $openstack->objectStoreV1()->listContainers();

The response stills Client error:POST https://lon.identity.api.rackspacecloud.com/v2.0/tokensresulted in a401 Unauthorizedresponse: {"unauthorized":{"code":401,"message":"Error code: 'AUTH-004'; Unable to authenticate user with credentials provided."}}

kynx commented 3 years ago

@braisdesousa We use this with Rackspace.

I can't remember doing it, but it looks like Rackspace expects 'apiKey', not 'password' and that we're overriding the default OpenStack\Identity\v2\Api to accomplish that. It's mixed in with stuff like caching the auth token and guzzle retry middleware. But from a quick look the relevant bits are:

use OpenStack\Identity\v2\Api as OpenStackApi;

class Api extends OpenStackApi
{
    protected $params;

    public function __construct()
    {
        $this->params = new Params();
    }

    public function postToken(): array 
    {
        return [
            'method' => 'POST',
            'path'   => 'tokens',
            'params' => [
                'username' => $this->params->username(),
                'apiKey'   => $this->params->apiKey(),
            ],
        ];
    }
}

and

use OpenStack\Common\Api\AbstractParams;

class Params extends AbstractParams
{
    public function username()
    {
        return [
            'type'     => self::STRING_TYPE,
            'location' => self::JSON,
            'path'     => 'auth.RAX-KSKEY:apiKeyCredentials',
            'required' => true,
        ];
    }

    public function apiKey()
    {
        return [
            'type'     => self::STRING_TYPE,
            'location' => self::JSON,
            'path'     => 'auth.RAX-KSKEY:apiKeyCredentials',
            'required' => true,
        ];
    }
}

Then the config looks something like:

$options = [
    'authUrl'         => $config['auth_url'],
    'region'          => $config['region'],
    'username'        => $config['username'],
    'apiKey'          => $config['api_key'],
];

You'd need to construct an instance of the Identity service passing the api as the second param, and somehow tell the rest of openstack to use that. As I said, our requirements are complex and there may be a much easier way of doing it.

Sure would have been nice if Rackspace hadn't fired all their developers 4 years ago ;)

braisdesousa commented 3 years ago

Thank you @kynx ! I will give it a Try ASAP and reply if it works.

braisdesousa commented 3 years ago

It Works as expected, the only required extra change is having to EDIT OpenStack Builder, to make a replacement of the API and the Service class, to match the ones we have created. Somthing as UGLY as this

 if($apiClass==='OpenStack\Identity\v2\Api'){
            $serviceClass=Service::class;
            $apiClass=Api::class;
        }

I'm not so happy with this solution. Looks like a horrible patch. But it works, which is what my company need right now. I'll try to write Rackspace Support for looking for a better solution than this one. But, anyway thanks @kynx @haphan for your incredible help. Couldn't make it without you.

gkilwein commented 2 years ago

I struggled with getting OpenStack working with Rackspace Cloud Files for days so I wrote my own very simple PHP client for the basic functionality that my app needs for Cloud Files here: https://github.com/gkilwein/Rackspace-Cloud-Files Hopefully this helps someone.