Skip to content

Commit

Permalink
Merge pull request #746 from tenable/io-credentials-upload
Browse files Browse the repository at this point in the history
Support for fileType Query Param in POST: credentials/files for Vulnerability Management
  • Loading branch information
aseemsavio authored Jan 12, 2024
2 parents 7a2ff8d + 65a9956 commit d8ad04e
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 6 deletions.
16 changes: 13 additions & 3 deletions tenable/io/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
.. autoclass:: CredentialsAPI
:members:
'''
from typing import BinaryIO

from tenable.utils import dict_merge
from .base import TIOEndpoint, TIOIterator

Expand Down Expand Up @@ -364,7 +366,7 @@ def list(self, *filters, **kw):
_resource='credentials'
)

def upload(self, fobj):
def upload(self, fobj: BinaryIO, file_type: str):
'''
Uploads a file for use with a managed credential.
Expand All @@ -373,10 +375,18 @@ def upload(self, fobj):
Args:
fobj (FileObject):
The file object intended to be uploaded into Tenable Vulnerability Management.
file_type (string):
File type of the credential being uploaded.
Returns:
:obj:`str`:
The fileuploaded attribute
Examples:
>>> with open("hello.pem", "rb") as file:
... response = tio.credentials.upload(file, "pem")
...
... print(response)
'''

# We will attempt to discover the name of the file stored within the
Expand All @@ -388,5 +398,5 @@ def upload(self, fobj):
'Filedata': fobj
}
}

return self._api.post('credentials/files', **kw).json()['fileuploaded']
file_type = self._check("file_type", file_type, str, choices=["pem", "json", "csv", "x.509", "p12", "ssh", "cookie"])
return self._api.post(f'credentials/files?fileType={file_type}', **kw).json()['fileuploaded']
75 changes: 75 additions & 0 deletions tests/io/cassettes/test_credentials_upload_should_succeed.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
interactions:
- request:
body: "--4771e568faa0dbd0b110440be90c7ac1\r\nContent-Disposition: form-data; name=\"Filedata\";
filename=\"Filedata\"\r\n\r\nHello World\r\n--4771e568faa0dbd0b110440be90c7ac1--\r\n"
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '159'
Content-Type:
- multipart/form-data; boundary=4771e568faa0dbd0b110440be90c7ac1
User-Agent:
- Integration/1.0 (pytest; pytenable-automated-testing; Build/unknown) pyTenable/1.4.16
(Restfly/1.4.7; Python/3.10.6; Darwin/arm64)
X-APIKeys:
- accessKey=TIO_ACCESS_KEY;secretKey=TIO_SECRET_KEY
method: POST
uri: https://cloud.tenable.com/credentials/files?fileType=pem
response:
body:
string: !!binary |
H4sIAAAAAAAAA6pWSsvMSS0tyMlPTElNUbJScsvMSU1JLEmMNzJJMU42NjTQNbFMNNY1SUxJ0k20
SE7RNTexSLQ0tDRKszAxUaoFAAAA//8DAHSoZFdAAAAA
headers:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- 837d83b66894a907-MAA
Cache-Control:
- no-store
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json;charset=utf-8
Date:
- Tue, 19 Dec 2023 06:16:03 GMT
Expect-CT:
- enforce, max-age=86400
NEL:
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
Pragma:
- no-cache
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=zYnBNXSL05uwOXdJUC%2FBt20UsbCrYVs5VfQT8oRLUlsC%2B371yiiqFPYbdaVKoRG9a0C6%2BQNw77W2sDitAWmQS77QYyxx1tLB2uSvH5ghL8te1P4BDwV77zCs1yXKQEQE%2BNtX"}],"group":"cf-nel","max_age":604800}'
Server:
- cloudflare
Set-Cookie:
- nginx-cloud-site-id=us-2b; path=/; HttpOnly; SameSite=Strict; Secure
- nginx-cloud-site-id=us-2b; path=/; HttpOnly; SameSite=Strict; Secure
Strict-Transport-Security:
- max-age=63072000; includeSubDomains
Transfer-Encoding:
- chunked
Vary:
- origin
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-Gateway-Site-ID:
- service-nginx-router-ap-south-1-prod-dc984846c-hltqr
X-Request-Uuid:
- b82eed07f9d8355fd6f8d7a4354d3647
X-Xss-Protection:
- 1; mode=block
status:
code: 200
message: OK
version: 1
35 changes: 32 additions & 3 deletions tests/io/test_credentials.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'''
test credentials
'''
import io
import uuid

import pytest
Expand Down Expand Up @@ -376,11 +377,39 @@ def test_credentials_list(api):


@pytest.mark.vcr()
def test_credentials_upload(api):
def test_credentials_upload_type_error(api):
'''
test to upload the credentials
test to raise error when the type param is not set.
'''
api.credentials.upload('ExampleDataGoesHere')

# Create a BytesIO object
file = io.BytesIO(b'\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64')

with pytest.raises(TypeError):
api.credentials.upload(file)

@pytest.mark.vcr()
def test_credentials_upload_should_fail_on_unsupported_type(api):
'''
test to raise error when the type param is not set.
'''

# Create a BytesIO object
file = io.BytesIO(b'\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64')

with pytest.raises(UnexpectedValueError):
api.credentials.upload(file, "some_type")

@pytest.mark.vcr()
def test_credentials_upload_should_succeed(api):
'''
test to succeed only when all the values are set properly.
'''

# Create a BytesIO object
file = io.BytesIO(b'\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64')
uploaded_file = api.credentials.upload(file, "pem")
assert type(uploaded_file) is str


@pytest.mark.vcr()
Expand Down

0 comments on commit d8ad04e

Please sign in to comment.