diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2dced6e37..e0dfb6145 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ and this project adheres to [Calendar Versioning](https://calver.org)html).
## [Unreleased]
### Added
### Changed
+* `get_feed` can also be requested with `GVMD_DATA` for 20.08 and newer, added `GVMD_DATA` to the FeedType and updated API call [#434](https://github.com/greenbone/python-gvm/pull/434)
+
### Deprecated
### Removed
### Fixed
diff --git a/gvm/protocols/gmpv208/gmpv208.py b/gvm/protocols/gmpv208/gmpv208.py
index c43dbeb73..4d8dcbf73 100644
--- a/gvm/protocols/gmpv208/gmpv208.py
+++ b/gvm/protocols/gmpv208/gmpv208.py
@@ -354,3 +354,29 @@ def create_target(
cmd.add_element("port_list", attrs={"id": port_list_id})
return self._send_xml_command(cmd)
+
+ def get_feed(self, feed_type: Optional[FeedType]) -> Any:
+ """Request a single feed
+
+ Arguments:
+ feed_type: Type of single feed to get: NVT, CERT or SCAP
+
+ Returns:
+ The response. See :py:meth:`send_command` for details.
+ """
+ if not feed_type:
+ raise RequiredArgument(
+ function=self.get_feed.__name__, argument='feed_type'
+ )
+
+ if not isinstance(feed_type, FeedType):
+ raise InvalidArgumentType(
+ function=self.get_feed.__name__,
+ argument='feed_type',
+ arg_type=FeedType.__name__,
+ )
+
+ cmd = XmlCommand("get_feeds")
+ cmd.set_attribute("type", feed_type.value)
+
+ return self._send_xml_command(cmd)
diff --git a/gvm/protocols/gmpv208/types.py b/gvm/protocols/gmpv208/types.py
index 1dc22a559..2bc13b3f8 100644
--- a/gvm/protocols/gmpv208/types.py
+++ b/gvm/protocols/gmpv208/types.py
@@ -31,7 +31,6 @@
AssetType,
CredentialFormat,
CredentialType,
- FeedType,
HostsOrdering,
PermissionSubjectType,
PortRangeType,
@@ -52,7 +51,6 @@
get_asset_type_from_string,
get_credential_format_from_string,
get_credential_type_from_string,
- get_feed_type_from_string,
get_hosts_ordering_from_string,
get_permission_subject_type_from_string,
get_port_range_type_from_string,
@@ -191,6 +189,28 @@ def get_entity_type_from_string(
) from None
+class FeedType(Enum):
+ """Enum for feed types"""
+
+ NVT = "NVT"
+ CERT = "CERT"
+ SCAP = "SCAP"
+ GVMD_DATA = "GVMD_DATA"
+
+
+def get_feed_type_from_string(feed_type: Optional[str]) -> Optional[FeedType]:
+ """Convert a feed type string into a FeedType instance"""
+ if not feed_type:
+ return None
+
+ try:
+ return FeedType[feed_type.upper()]
+ except KeyError:
+ raise InvalidArgument(
+ argument='feed_type', function=get_feed_type_from_string.__name__
+ ) from None
+
+
class FilterType(Enum):
"""Enum for filter types"""
diff --git a/tests/protocols/gmpv208/test_new_gmpv208.py b/tests/protocols/gmpv208/test_new_gmpv208.py
index 4589457c9..6f7123cb9 100644
--- a/tests/protocols/gmpv208/test_new_gmpv208.py
+++ b/tests/protocols/gmpv208/test_new_gmpv208.py
@@ -74,3 +74,7 @@ class Gmpv208ModifyReportFormatTestCase(
class Gmpv208ModifyTagTestCase(GmpModifyTagTestCase, Gmpv208TestCase):
pass
+
+
+class Gmpv208GetFeedTestCase(GmpGetFeedTestCase, Gmpv208TestCase):
+ pass
diff --git a/tests/protocols/gmpv208/test_v7_from_gmpv208.py b/tests/protocols/gmpv208/test_v7_from_gmpv208.py
index d1cd100b6..54e0be48b 100644
--- a/tests/protocols/gmpv208/test_v7_from_gmpv208.py
+++ b/tests/protocols/gmpv208/test_v7_from_gmpv208.py
@@ -266,10 +266,6 @@ class Gmpv208GetCredentialsTestCase(GmpGetCredentialsTestCase, Gmpv208TestCase):
pass
-class Gmpv208GetFeedTestCase(GmpGetFeedTestCase, Gmpv208TestCase):
- pass
-
-
class Gmpv208GetFeedsTestCase(GmpGetFeedsTestCase, Gmpv208TestCase):
pass
diff --git a/tests/protocols/gmpv208/testcmds/__init__.py b/tests/protocols/gmpv208/testcmds/__init__.py
index 8deb87aae..d63afc8af 100644
--- a/tests/protocols/gmpv208/testcmds/__init__.py
+++ b/tests/protocols/gmpv208/testcmds/__init__.py
@@ -30,3 +30,4 @@
from .test_modify_permission import GmpModifyPermissionTestCase
from .test_modify_report_format import GmpModifyReportFormatTestCase
from .test_modify_tag import GmpModifyTagTestCase
+from .test_get_feed import GmpGetFeedTestCase
diff --git a/tests/protocols/gmpv208/testcmds/test_get_feed.py b/tests/protocols/gmpv208/testcmds/test_get_feed.py
new file mode 100644
index 000000000..73350dfe8
--- /dev/null
+++ b/tests/protocols/gmpv208/testcmds/test_get_feed.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2018-2021 Greenbone Networks GmbH
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import unittest
+
+from gvm.errors import RequiredArgument, InvalidArgumentType
+
+from gvm.protocols.gmpv208 import FeedType
+
+
+class GmpGetFeedTestCase:
+ def test_get_feed(self):
+ """
+ Test basic get_feed calls with only resource_type except special
+ cases for audit, policy, scan_config and task.
+ """
+ self.gmp.get_feed(FeedType.NVT)
+
+ self.connection.send.has_been_called_with('')
+
+ self.gmp.get_feed(FeedType.CERT)
+
+ self.connection.send.has_been_called_with('')
+
+ self.gmp.get_feed(FeedType.SCAP)
+
+ self.connection.send.has_been_called_with('')
+
+ self.gmp.get_feed(FeedType.GVMD_DATA)
+
+ self.connection.send.has_been_called_with(
+ ''
+ )
+
+ def test_get_feed_missing_type(self):
+ """
+ Test get_feed calls with missing resource_type
+ """
+ with self.assertRaises(RequiredArgument):
+ self.gmp.get_feed(feed_type=None)
+
+ with self.assertRaises(RequiredArgument):
+ self.gmp.get_feed(feed_type='')
+
+ with self.assertRaises(RequiredArgument):
+ self.gmp.get_feed('')
+
+ def test_get_feed_invalid_type(self):
+ """
+ Test get_feed calls with invalid resource_type
+ """
+ with self.assertRaises(InvalidArgumentType):
+ self.gmp.get_feed('foo')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/protocols/gmpv208/testtypes/test_feed_type.py b/tests/protocols/gmpv208/testtypes/test_feed_type.py
new file mode 100644
index 000000000..5bd3d26cf
--- /dev/null
+++ b/tests/protocols/gmpv208/testtypes/test_feed_type.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2019-2021 Greenbone Networks GmbH
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import unittest
+
+from gvm.errors import InvalidArgument
+from gvm.protocols.gmpv208 import FeedType, get_feed_type_from_string
+
+
+class GetFeedTypeFromStringTestCase(unittest.TestCase):
+ def test_invalid(self):
+ with self.assertRaises(InvalidArgument):
+ get_feed_type_from_string('foo')
+
+ def test_none_or_empty(self):
+ ct = get_feed_type_from_string(None)
+ self.assertIsNone(ct)
+ ct = get_feed_type_from_string('')
+ self.assertIsNone(ct)
+
+ def test_nvt(self):
+ ct = get_feed_type_from_string('nvt')
+ self.assertEqual(ct, FeedType.NVT)
+
+ def test_cert(self):
+ ct = get_feed_type_from_string('cert')
+ self.assertEqual(ct, FeedType.CERT)
+
+ def test_scap(self):
+ ct = get_feed_type_from_string('scap')
+ self.assertEqual(ct, FeedType.SCAP)
+
+ def test_gvmd_data(self):
+ ct = get_feed_type_from_string('gvmd_data')
+ self.assertEqual(ct, FeedType.GVMD_DATA)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/protocols/gmpv214/test_v208_from_gmpv214.py b/tests/protocols/gmpv214/test_v208_from_gmpv214.py
index 3482b1268..8f28c5d8e 100644
--- a/tests/protocols/gmpv214/test_v208_from_gmpv214.py
+++ b/tests/protocols/gmpv214/test_v208_from_gmpv214.py
@@ -68,3 +68,7 @@ class Gmpv214ModifyReportFormatTestCase(
class Gmpv214ModifyTagTestCase(GmpModifyTagTestCase, Gmpv214TestCase):
pass
+
+
+class Gmpv214GetFeedTestCase(GmpGetFeedTestCase, Gmpv214TestCase):
+ pass
diff --git a/tests/protocols/gmpv214/test_v7_from_gmpv214.py b/tests/protocols/gmpv214/test_v7_from_gmpv214.py
index e1827183d..718c31532 100644
--- a/tests/protocols/gmpv214/test_v7_from_gmpv214.py
+++ b/tests/protocols/gmpv214/test_v7_from_gmpv214.py
@@ -258,10 +258,6 @@ class Gmpv214GetCredentialsTestCase(GmpGetCredentialsTestCase, Gmpv214TestCase):
pass
-class Gmpv214GetFeedTestCase(GmpGetFeedTestCase, Gmpv214TestCase):
- pass
-
-
class Gmpv214GetFeedsTestCase(GmpGetFeedsTestCase, Gmpv214TestCase):
pass